【问题标题】:is not a function, when function is right above?不是函数,什么时候函数就在上面?
【发布时间】:2022-01-07 07:24:19
【问题描述】:

我经常遇到无法在 js 类中访问我的 js 类的函数的问题。 我主要用这个来修复它。或 bind(this) 但为什么这不起作用?它与我在另一个班级中这样做的方式完全相同。

class Page {

     // constructor and props

     ShowNewJobPopup() {
        var popupNewJobElement = $("<div>").attr("id", "popupNewJob");
        console.log(data, element);
    }

    InitializeFilterElements(filterItems) {
        filterItems["Control"].Items.push({
            Template: function (itemElement) {
                itemElement.append("<div id=\"btnNeuerJob\" style=\"width: 100%; margin-top: 4px;\"></div>");
                $("#btnNeuerJob").dxButton({
                    type: "default",
                    text: "Neuer Job",
                    disabled: false,
                    onClick: function () {
                        this.ShowNewJobPopup(); // how is this not a function
                        
                    }.bind(this)
                });
            }
        });
        return filterItems;
    }
}

当我在开发控制台中时。我可以写 Page.ShowNewJobPopup (Page 是附加的脚本)

【问题讨论】:

  • this.ShowNewJobPopup() -> console.log(this) -> this = #btnNeuerJob(可能没有勾选dxButton

标签: javascript jquery function this devextreme


【解决方案1】:

this 实际上不是来自 Page 类。

我们通过以下方式重写您的 Page 类,您可以看到 this 引用了 obj

class Page {
    constructor() {}

    ShowNewJobPopup() {
        var popupNewJobElement = $("<div>").attr("id", "popupNewJob");
        console.log(data, element);
    }

    InitializeFilterElements(filterItems) {
        const obj = {
            Template: function (itemElement) {
                itemElement.append(
                    '<div id="btnNeuerJob" style="width: 100%; margin-top: 4px;"></div>'
                );
                $("#btnNeuerJob").dxButton({
                    type: "default",
                    text: "Neuer Job",
                    disabled: false,
                    onClick: function () {
                        this.ShowNewJobPopup(); 
                    }.bind(this), // this is referred to obj
                });
            },
        };

        filterItems["Control"].Items.push(obj);
        return filterItems;
    }
}

您可以做的是创建一个变量self 来存储this 并稍后使用它来引用Page 类。

class Page {
    constructor() {}

    ShowNewJobPopup() {
        var popupNewJobElement = $("<div>").attr("id", "popupNewJob");
        console.log(data, element);
    }

    InitializeFilterElements(filterItems) {
        const self = this; // this here is referred to the class Page

        const obj = {
            Template: function (itemElement) {
                itemElement.append(
                    '<div id="btnNeuerJob" style="width: 100%; margin-top: 4px;"></div>'
                );
                $("#btnNeuerJob").dxButton({
                    type: "default",
                    text: "Neuer Job",
                    disabled: false,
                    onClick: function () {
                        self.ShowNewJobPopup(); // self is referred to Page Class
                    },
                });
            },
        };

        filterItems["Control"].Items.push(obj);
        return filterItems;
    }
}

【讨论】:

  • 很好地解释了这里的问题,这很有效。 (也可能是所有其他人)我认为我们在 JS 中的这一理念(我们来自 c#)非常愚蠢,需要重新考虑我们的做法。谢谢
【解决方案2】:

您似乎有多个具有不同this 上下文的函数相互嵌套。在类方法的顶部创建一个变量会简单得多,而不用担心将正确的上下文传递给每个函数。

InitializeFilterElements(filterItems) {
    const thisPage = this; // SET THE VARIABLE
    filterItems["Control"].Items.push({
        Template: function (itemElement) {
            itemElement.append("<div id=\"btnNeuerJob\" style=\"width: 100%; margin-top: 4px;\"></div>");
            $("#btnNeuerJob").dxButton({
                type: "default",
                text: "Neuer Job",
                disabled: false,
                onClick: function () {
                    thisPage.ShowNewJobPopup();                    
                }
            });
        }
    });
    return filterItems;
}

【讨论】:

    【解决方案3】:

    this 的值取决于函数的调用方式(运行时绑定)。执行时不能通过赋值来设置,每次调用函数时可能都不一样。

    InitializeFilterElements(filterItems) {
        const self = this; // self now holds the value of this reference
        filterItems["Control"].Items.push({
            Template: function (itemElement) {
                itemElement.append("<div id=\"btnNeuerJob\" style=\"width: 100%; margin-top: 4px;\"></div>");
                $("#btnNeuerJob").dxButton({
                    type: "default",
                    text: "Neuer Job",
                    disabled: false,
                    onClick: function () {
                        self.ShowNewJobPopup();                    
                    }
                });
            }
        });
        return filterItems;
    }
    

    【讨论】:

      【解决方案4】:

      这是 JavaScript 中this 的经典问题。当调用Template 函数时,this 的引用将更改为调用该函数的对象的上下文。

      检查错误示例

      一个可能的解决办法是

      class Page {
      
       // constructor and props
      
       ShowNewJobPopup() {
          var popupNewJobElement = $("<div>").attr("id", "popupNewJob");
          console.log(data, element);
      }
      
      InitializeFilterElements(filterItems) {
          var that = this;
          filterItems["Control"].Items.push({
              Template: function (itemElement) {
                  itemElement.append("<div id=\"btnNeuerJob\" style=\"width: 100%; margin-top: 4px;\"></div>");
                  $("#btnNeuerJob").dxButton({
                      type: "default",
                      text: "Neuer Job",
                      disabled: false,
                      onClick: function () {
                          this.ShowNewJobPopup(); // how is this not a function
                          
                      }.bind(that)
                  });
              }
          });
          return filterItems;
      }
      

      }

      class A {
      
        test() {
          console.log("test")
        }
      
        test2() {
          let a = []
          a.push({
            template() {
              function abc() {
                console.log(this)
                this.test()
              }
              abc.bind(this)()
            }
          })
          return a
        }
      
      }
      
      let a = new A()
      
      let arr = a.test2()
      
      //this will work
      arr[0].template.bind(a)()
      console.log("===========")
      arr[0].template()

      【讨论】:

        猜你喜欢
        • 2011-02-21
        • 1970-01-01
        • 1970-01-01
        • 2015-04-05
        • 2019-10-16
        相关资源
        最近更新 更多