Javascript 什么';在knockout.js视图模型中使用'var self=this'的优点是什么

Javascript 什么';在knockout.js视图模型中使用'var self=this'的优点是什么,javascript,knockout.js,Javascript,Knockout.js,在几乎所有的knockout.js视图示例中,我都看到行var self=this,然后所有局部变量都是引用self.variableName。与使用this.variableName相比,这种方法的优点是什么?Self用于确保将原始this保存在对象中 这在使用事件处理程序等时非常方便 你可以阅读更多关于这方面的内容 第一个答案基本上涵盖了这一点,也显示了一个很好的链接。请查看。通常使用此方法的主要原因是使当前的this可用于子函数或闭包。例如: var myObject = { para

在几乎所有的knockout.js视图示例中,我都看到行
var self=this
,然后所有局部变量都是引用
self.variableName
。与使用
this.variableName
相比,这种方法的优点是什么?

Self
用于确保将原始
this
保存在对象中

这在使用事件处理程序等时非常方便

你可以阅读更多关于这方面的内容


第一个答案基本上涵盖了这一点,也显示了一个很好的链接。请查看。

通常使用此方法的主要原因是使当前的
this
可用于子函数或闭包。例如:

var myObject = {
  param: 123,
  method: function(){
    alert( this.param );
  },
  method2: function(){
    setTimeout(function(){
      alert( this.param );
    },100);
  }
}
在上面的调用中,
myObject.method
将为您提供
123
的正确警报。但是,调用
myObject.method2
将为您提供
未定义的
。这是因为与
setTimeout
一起使用的匿名函数中的
This
没有引用
myObject
,这取决于JavaScript解释器,它将指向不同的东西。但是,如果您有:

method2: function(){
  var self = this;
  setTimeout(function(){
    alert( self.param );
  },100);
}
这是因为捕获了位于正确点的
的当前状态,并将始终为每个可用的功能范围引用
myObject

问题不限于使用
setTimeout
。在任何有匿名函数、子函数或闭包的地方,这个技巧都会派上用场。有时人们使用
self
,或
that
或更具描述性的东西,具体取决于当前引用所代表的内容


而不是作为变量存储 除了使用
self
或任何其他变量“记住”任何特定点的状态外,还有一种替代方法,即使用特定上下文“绑定”匿名函数或子函数。许多现代口译员现在支持
Function.prototype.bind
方法,该方法可用于:

var method = function(){
  console.log(this);
};
var methodWithWindow = method.bind(window);
var methodWithDocument = method.bind(document);
var methodWithObject = method.bind({random:"object"});
依次调用每个绑定方法将获得以下控制台输出:

Window
Document
Object {random:"object"}
如果您希望支持较旧的浏览器,您可以使用一个,或者如果您更喜欢一个更简单的实现,一个不担心绑定参数的实现。绑定代码的基本功能如下:

!Function.prototype.bind && (Function.prototype.bind = function(context){
  var method = this;
  return function(){
    method.apply(context, arguments);
  }
})
那么,使用bind时最初的示例会是什么样子呢

method2: function(){
  setTimeout((function(){
    console.log(this); // `this` will be the same as the `this` passed to bind.
  }).bind(this),100);
}
如上所述,一旦绑定,返回的函数(闭包)将保留指定的上下文;因此,它可以在任何你想要的地方传递,并且仍然保留对你想要的对象的
引用。这在
method2
示例中很有用,因为我们将该方法与当前上下文捆绑在一起,并将其传递给
setTimeout
,后者稍后将执行绑定方法(在我们退出当前块执行很久之后)

当使用
self
或任何其他变量时,也会发生同样的情况。变量将被捕获到函数的作用域链中,并且在函数最终被再次调用时仍然可以访问。使用
bind
的好处是,如果愿意,您可以轻松重写上下文,您必须编写自己的特定方法来重写
self
变量

警告:值得注意的是,绑定函数时,会返回一个新函数。如果将绑定函数与事件侦听器混合使用,然后尝试使用原始函数而不是绑定版本删除侦听器,则可能会导致混乱的情况

另外,由于绑定返回一个新函数,如果绑定一个绑定函数,实际上就是在用另一个函数将一个函数包装到一个函数中。您应该意识到这一点,因为它会影响性能,而且在避免内存泄漏方面,管理起来会更加棘手。我首选的绑定方法是使用闭包和它们自己的解构方法(即依靠self,但确保有方法取消它的内容),但这需要更多的前瞻性思考,在较小的JS项目中不太相关;或一次性函数绑定-特别是如果绑定方法从未在任何引用中捕获


没有自我约束? 还值得一提的是,有时您可以在根本不使用
bind
的情况下获得相同的结果,而是使用
apply
——这应该在您可以选择使用的任何内容中本机可用。主要区别在于,函数中没有任何内容,调用apply实际上是在那里执行函数,然后使用不同的上下文(传递给apply的第一个参数)执行函数

var externalMethod = function(){
  console.log(this); // will output myObject when called below
};

var myObject = {
  method2: function(){
    externalMethod.apply(this);
  }
};

这是什么?
在删除最近的评论之前,请详细说明此答案,并提供有关此
的更多详细信息<代码>此
将引用以下四项之一,具体取决于您在其中使用的函数的调用方式:

myObject.method()
除非
方法
应用了
.bind(context)
操作,否则上面将有一个
this
myObject
。在这种情况下,
将是最后绑定的上下文

unattachedFunction()
anyFunction.apply(otherObject)
将有一个全局上下文的
(在浏览器环境中通常是
窗口
),除非
unattachedFunction
应用了
.bind(context)
操作。在这种情况下,
将是最后绑定的上下文

unattachedFunction()
anyFunction.apply(otherObject)

两者都将始终具有
this
otherObject
,因为以这种方式调用将覆盖任何绑定

new myObject()
将有一个
this
引用
myObject
的新实例,这将覆盖任何绑定

new myObject()

简单思维实验 考虑到以上所有因素,该
将包含哪些内容<