如何从嵌套函数引用类变量/方法



class Foo {
  constructor() {
    this.foobar = "foobar";
  }
  bar() {
    let _this = this;
    return function() {
      try {
        alert("Attempt 1: "+foobar);//ReferenceError: foobar is not defined
        myMethod();
      } catch(err) {console.log(err);}
      try {
        alert("Attempt 2: "+this.foobar);//TypeError: this is undefined
        this.myMethod();
      } catch(err) {console.log(err);}
      try{
        alert("Attempt 3: "+_this.foobar);//Works!
        _this.myMethod();
      } catch(err) {console.log(err);}
    }();
  }
  myMethod() {
    alert("myMethod()");
  }
}
new Foo().bar();

上面的例子非常简化 - bar()中的匿名函数最初是一个jQuery调用,但为了这个问题,我没有包括它。

为什么尝试 1 和 2 不起作用?我必须使用_this技巧来引用类变量/方法吗?如何从嵌套函数引用类变量/方法?

你熟悉 this 关键字在 JavaScript 中的工作原理吗?它的值将取决于函数的调用方式,而不是如何定义函数。例如,如果执行以下操作:

var dog = {
  greeting:"woof",
  talk:function (){
    console.log(this.greeting);
  }
};
var cat={
  greeting:"meow",
  talk:dog.talk
};
dog.talk();
cat.talk();

您将看到,当 talk 函数作为对象的方法调用时,该对象将用作 this 的值。

ES6 类也是如此,其中类方法仍然是 JavaScript 函数,并且决定this值的规则仍然适用。如果你想避免声明一个辅助变量,你应该考虑使用bind

var mammal = {
  greeting:"<noise>",
  getTalk:function (){
    return function(){
      console.log(this.greeting);
    };
  },
  getTalkBinded:function (){
    return (function(){
      console.log(this.greeting)
    }).bind(this);
  }
};
var dog={
  greeting:"woof",
  talk:mammal.getTalk(),
  talkBinded:mammal.getTalkBinded()
};
var cat={
  greeting:"meow",
  talk:mammal.getTalk(),
  talkBinded:mammal.getTalkBinded()
};
dog.talk();
cat.talk();
dog.talkBinded();
cat.talkBinded();

您正在返回自执行函数执行结果,并且在该函数执行期间this全局上下文(不是您的类对象(。 要使其正常工作() => {}()请使用箭头函数调用语法,因为它捕获当前上下文或function() { }.bind(this)()

看这个简单的例子,

function a(){
    this.someProp = 5;
    console.log(this);
    var _this = this;   //so we explicitly store the value of `this` to use in a nested function
    return function(){
        //value of `this` will change inside this function
        this.anotherProp = 6;
        console.log(this);
        //to use the methods and props of original function use `_this`
        console.log(_this)
    }
}
var c = a.call({})  //prints {someProp: 5}
c.call({})    //prints {anotherProps: 6} {someProp: 5}

最新更新