7

我在 JavaScript 中看到过很多这样的事情,我记得找出原因,但我不记得答案了。

我猜这与范围和在“类”之外调用的函数有关,但为什么要这样做(最好概述一个示例):

function myClass ()
{
    var self = this;

    //...

    this.myArray = [];

    this.myFunc = function () { alert(self.myArray.length); };
}
4

5 回答 5

5

为了将变量锁定为闭包的一部分。

例如:

MyClass.prototype.doStuff = function(){
  this.foundItems = [];
  var self = this;
  this.myString.replace(/.../,function(){
    // `this` is actually the `window` inside this callback
    // so we need to use `self` to invoke another method on our instance object
    self.foundItems.push( self.doOtherStuff() );
  });
};

如果您以预期的方式调用该方法,则您编写的特定示例不需要闭包:

function Foo(){
  this.array = [];
  this.myFunc = function(){
    return this.array;
  }
}
var foo = new Foo;
foo.myFunc(); // []

但是,可以像这样“破坏”它:

var f2 = foo.myFunc;
f2(); // undefined, since `this` was the window

另一方面,使用闭包的代码对这种愚蠢行为是安全的。

于 2012-05-30T15:08:48.650 回答
2

“this”指的是当前的“对象”。在谈论 javascript 时,权力在于“this”表达式是根据上下文评估的,例如,如果一个方法在另一个对象上下文中执行,“this”值将分别改变。

于 2012-05-30T15:10:17.147 回答
1

如果您在另一个函数中创建一个函数,this则内部函数将设置为全局窗口对象。如果您创建一个保存 的值的变量this,例如

var that = this;

然后您可以使用that在内部函数中引用外部函数。

于 2012-05-30T15:12:56.060 回答
0

除了其他用户发布的一些答案之外,创建变量集允许您在不访问对象的情况下重用变量。

类似于做类似的事情:

var myElement = document.getElementById('someElement');

然后在需要时访问 myElement 而不是 document.getElementById 多次。

设置 that = this 或 self = this 使您可以在任何地方访问“that”或“self”,并防止重新加载某些对象。

于 2012-05-30T15:19:36.037 回答
0

我不认为一个人真的想这样做:

  • 每当创建实例时,您也会创建函数的“副本”。所以 5 个实例,将创建函数的 5 个“副本”。
  • 函数的“副本”绑定到仅与该特定实例相关的环境,因此不能通用。这意味着扩展类将获得一个仅与父类的某些实例相关的方法,该实例可能甚至未使用。
  • 你的缩进会失控,特别是如果你开始嵌套那些内联函数
  • 您必须在其他函数中寻找函数,而不仅仅是在原型定义中查找它

替代:

function MyClass() {
    this.myArray = [];
    this.myFunc = this.myFunc.bind(this); //The "blueprint" in the prototype is not affected, the instance gets its own bound version.
                                           //This means the one in prototype can be inherited or used generically anywhere else as well
}

MyClass.prototype = {

    myFunc: function() { //My func is neatly listed in the prototype and can use `this` normally
        alert(this.myArray.length);
    },

    constructor: MyClass
};


var myObj = new MyClass();

document.addEventListener( "click", myObj.myFunc ); //Will now work as you "expect" it to work

一些缺点:

  • 每个绑定函数都是一个新函数,因此每个实例,每次仍然创建 1 个新函数。
  • 写出.bind构造函数中的所有调用的样板文件,尽管可以通过像这样的助手来缓解_.bindAll
于 2012-05-30T15:53:40.003 回答