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
What's the advantage of using `var self = this` in knockout.js view models
提问by Neil
I see in almost all examples of a knockout.js viewmodels the line var self = this
and 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 this
available 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.method
will give you the correct alert of 123
. However calling myObject.method2
will give you undefined
. This is because this
inside the anonymous function used with setTimeout
does 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 myObject
for 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 that
or 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 self
or 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.bind
method, 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 this
reference to the object you want. This is useful in the method2
example because we bundle the method up with our current context and pass it to setTimeout
which 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 self
or 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 bind
however 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 self
variable.
使用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 bind
at 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. this
will 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 this
of myObject
, unless method
has had a .bind(context)
operation applied. In which case this
will be whatever the last bound context was.
除非已应用操作,否则上述内容将具有this
of 。在这种情况下,无论最后绑定的上下文是什么。myObject
method
.bind(context)
this
unattachedFunction()
Will have a this
of the global context (usually window
in browser environments), unless unattachedFunction
has had a .bind(context)
operation applied. In which case this
will 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 this
of otherObject
, because calling in this way will override any binding.
两者都将始终具有this
of otherObject
,因为以这种方式调用将覆盖任何绑定。
new myObject()
Will have a this
that 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 this
be 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
Self
is used to make sure the original this
is 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. this
under Javascript behaves different than in other languages. For more details look at MDN Docs on this
它用于参考目的。this
在 Javascript 下的行为与其他语言不同。有关更多详细信息,请查看有关此的 MDN 文档