javascript 在knockout.js 视图模型中使用`var self = this` 有什么好处

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/17163248/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-27 07:19:54  来源:igfitidea点击:

What's the advantage of using `var self = this` in knockout.js view models

javascriptknockout.js

提问by Neil

I see in almost all examples of a knockout.js viewmodels the line var self = thisand then all local variables are references as self.variableName. What is the advantage of this over using this.variableName?

我在几乎所有 knockout.js viewmodels 示例中看到该行var self = this,然后所有局部变量都被引用为self.variableName. 这与使用相比有什么优势this.variableName

回答by Pebbl

Normally the main reason for using this approach is to make the current thisavailable to subfunctions or closures. For example:

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

var myObject = {
  param: 123,
  method: function(){
    alert( this.param );
  },
  method2: function(){
    setTimeout(function(){
      alert( this.param );
    },100);
  }
}

In the above calling myObject.methodwill give you the correct alert of 123. However calling myObject.method2will give you undefined. This is because thisinside the anonymous function used with setTimeoutdoes not refer to myObject, depending on the JavaScript interpreter it will point to different things. However, if you have:

在上面的调用中myObject.method会给你正确的提醒123。但是打电话myObject.method2会给你undefined。这是因为this在使用 with 的匿名函数内部setTimeout不引用myObject,根据 JavaScript 解释器它会指向不同的东西。但是,如果您有:

method2: function(){
  var self = this;
  setTimeout(function(){
    alert( self.param );
  },100);
}

This works because the current state of this— at the right point — is captured, and will always reference myObjectfor every function scope that it is available to.

这是有效的,因为当前状态this- 在正确的点 - 被捕获,并且将始终引用myObject它可用的每个函数范围。

The problem is not limited to the use of setTimeout. At any point where you have anonymous functions, subfunctions or closures this trick will come in handy. Sometimes people use self, or thator something a bit more descriptive depending on what the current reference represents.

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



rather than storing as a variable

而不是存储为变量

There is an alternative to using selfor any other variable to "remember" the state of this at any particular point, and that is to "bind" your anonymous or sub functions with a particular context. Many modern interpreters now support the Function.prototype.bindmethod, which can be used thusly:

除了使用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"});

Calling each of the bound methods in turn would give you the following console output:

依次调用每个绑定方法将为您提供以下控制台输出:

Window
Document
Object {random:"object"}

If you wish to support older browsers you can use a polyfill, or if you prefer a much simpler implementation, one that doesn't worry about binding arguments as well. The basics of what the bind code does is the following:

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

!Function.prototype.bind && (Function.prototype.bind = function(context){
  var method = this;
  return function(){
    method.apply(context, arguments);
  }
})

So, how would the initial example look using bind?

那么,使用 bind 的初始示例看起来如何?

method2: function(){
  setTimeout((function(){
    console.log(this); // `this` will be the same as the `this` passed to bind.
  }).bind(this),100);
}

As you can see above, once bound, the returned function (closure) retains that specified context; so it can be passed around where ever you want and still keep a thisreference to the object you want. This is useful in the method2example because we bundle the method up with our current context and pass it to setTimeoutwhich will execute the bound method later (long after we have exited the current block execution).

正如你在上面看到的,一旦绑定,返回的函数(闭包)会保留指定的上下文;所以它可以在任何你想要的地方传递,并且仍然保留this对你想要的对象的引用。这在method2示例中很有用,因为我们将方法与当前上下文捆绑在一起,并将其传递给setTimeout稍后将执行绑定方法(在我们退出当前块执行很久之后)。

The same does occur for when using selfor any other variable. The variable would be captured within the function's scope chain, and would still be there for access when the function is eventually called again. The benefit of using bindhowever is that you can override the context easily if you so wish, you would have to code your own specific methods to do so to override a selfvariable.

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

WARNING:It is worth noting here that when you bind a function, a new function is returned. This can cause confusing situations if you mix bound functions with event listeners and then attempt to remove the listeners using the original function rather than the bound version.

Also, because binding returns a new function, if you bind a bound function you are in fact wrapping a function in a function, with another function. You should be aware of this because it affects performance and will prove trickier to manage in terms of avoiding memory leaks. My preferred approach to binding is to use closures with their own deconstruction methods (i.e. rely on self, but make sure you have methods to nullify it's content), but this does take more forward thinking and is not so relevant in smaller JS projects; or one off function bindings — especially if the bound method is never caught in any reference.

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

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



without self and bind?

没有自我和束缚?

It is also worth mentioning that sometimes you can achieve the same result without using bindat all, and instead use apply— which should be natively available in anything you may choose to use. The major difference being that nothing is wrapped up with the function, and calling apply actually executes the function there and then with a different context — the first argument passed to apply.

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

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

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



What is this?

什么是this

Just to elaborate this answer with further detail about this— before the recent comments get deleted. thiswill refer to one of four things, depending on how the function you are using it within was called:

只是为了this在最近的评论被删除之前更详细地阐述这个答案。this将指四件事之一,具体取决于您在其中使用它的函数是如何被调用的:

myObject.method()

The above will have a thisof myObject, unless methodhas had a .bind(context)operation applied. In which case thiswill be whatever the last bound context was.

除非已应用操作,否则上述内容将具有thisof 。在这种情况下,无论最后绑定的上下文是什么。myObjectmethod.bind(context)this

unattachedFunction()

Will have a thisof the global context (usually windowin browser environments), unless unattachedFunctionhas had a .bind(context)operation applied. In which case thiswill be whatever the last bound context was.

将具有this全局上下文(通常window在浏览器环境中),除非unattachedFunction.bind(context)应用操作。在这种情况下,this无论最后绑定的上下文是什么。

anyFunction.apply(otherObject)

or

或者

anyFunction.call(otherObject)

Both will always have a thisof otherObject, because calling in this way will override any binding.

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

new myObject()

Will have a thisthat refers to a new instance of myObject, this will override any binding.

将有一个this指向 的新实例myObject,这将覆盖任何绑定。



Simple thought experiment

简单的思想实验

Taking all the above into account, what would thisbe inside referencedMethod?

考虑到以上所有因素,this里面会是referencedMethod什么?

var referencedMethod = myObject.method;
referencedMethod();

Correct!it will be the global context. This is why if you want to share methods with other objects or code — but still retain the original owner as context — you really need to either bind, or keep the function bundled with its owner object so you can call or apply.

正确的!这将是全球背景。这就是为什么如果您想与其他对象或代码共享方法——但仍保留原始所有者作为上下文——您确实需要绑定或保持函数与其所有者对象捆绑在一起,以便您可以调用或应用。

回答by Tikkes

Selfis used to make sure the original thisis maintained within the object.

Self用于确保原始文件this保留在对象内。

This comes in handy when using event handlers and so on.

这在使用事件处理程序等时会派上用场。

You can read more about this here

您可以在此处阅读有关此内容的更多信息

The first answer covers it basically, also it shows a good link. Check it out.

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

回答by Thomas Junk

It is used for reference purposes. thisunder Javascript behaves different than in other languages. For more details look at MDN Docs on this

它用于参考目的。this在 Javascript 下的行为与其他语言不同。有关更多详细信息,请查看有关此的 MDN 文档