在knockout.js 视图模型中使用`var self = this` 有什么好处 [英] What's the advantage of using `var self = this` in knockout.js view models

查看:20
本文介绍了在knockout.js 视图模型中使用`var self = this` 有什么好处的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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?

推荐答案

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

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

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

在上面调用myObject.method 会给你正确的警报123.但是调用 myObject.method2 会给你 undefined.这是因为与 setTimeout 一起使用的匿名函数中的 this 不引用 myObject,根据 JavaScript 解释器,它会指向不同的东西.但是,如果您有:

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:

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

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

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.

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

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.


除了使用 self 或任何其他变量来记住"任何特定点的状态之外,还有一种替代方法,那就是将您的匿名或子函数与特定上下文绑定".许多现代解释器现在支持 Function.prototype.bind 方法,可以这样使用:

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:

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"}

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

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:

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

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

So, how would the initial example look using bind?

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

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

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).

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

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.

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

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.

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

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.


还值得一提的是,有时完全不使用 bind 也可以达到相同的结果,而是使用 apply —它应该在您可以选择使用的任何内容中本地可用.主要区别在于该函数没有包含任何内容,并且调用 apply 实际上在那里执行该函数,然后使用不同的上下文 —传递给 apply 的第一个参数.

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.

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

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


只是为了详细说明这个答案,进一步详细说明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:

myObject.method()

上面将有一个 thismyObject,除非 method 有一个 .bind(context)操作应用.在这种情况下,this 将是最后一个绑定上下文.

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.

unattachedFunction()

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

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.

anyFunction.apply(otherObject)

anyFunction.call(otherObject)

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

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

new myObject()

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

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


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

Taking all the above into account, what would this be inside 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.

这篇关于在knockout.js 视图模型中使用`var self = this` 有什么好处的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆