我发现自己需要:
var self = this;
我的javascript“类”中有很多内容。尽管通常这样做,但感觉还是有些错误。我希望在这个问题中找到解决这个问题的更好方法,或者说服我这很正常的方法。
这是保持正确绑定的标准方法吗?我是否应该在所有地方都标准化使用“自我”,除非我明确需要“这个”。
编辑:我确切地知道为什么我需要这个,我只是想知道它是否被认为是邪恶的,为什么。我知道还有一个“应用”内置的javascript函数可以在调用方法时显式定义范围。这个会比较好吗?
Answers:
就像其他人所说的那样:“某种程度上,这个“额外变量”是解决这一事实的唯一方法,因为它this是一个特殊的表达式,因此不是变量,它不受执行上下文/闭包的约束。
但是,我认为您要问的(或我真正想回答的)是:
是否应该
var self = this在每个方法/构造函数的顶部放置一个?
当我尝试过一次并且有相同的问题时,我不再使用这种方法。现在,当需要在闭包中访问时,我保留该构造。对我来说,它增加了一点“嘿,这就是我真正想要的!” 我的代码的语义:
this -> this 和 self -> this (but really that) in a closure
...虽然通常这样做,但感觉还是有些错误。我希望在这个问题中找到解决这个问题的更好方法,或者说服我这样做的一切都很好。
做适合您的事情。不要害怕尝试一种方法,以后再切换回去(但请尝试在每个项目中保持一致:-)
这是保持正确绑定的标准方法吗?我是否应该在所有地方都标准化使用“自我”,除非我明确需要“这个”。
“自我”是最常用的名称。如上所述,我更喜欢使用相反的方法,this除非需要使用闭包绑定。
..如果认为它有点邪恶,为什么。
邪恶是一个愚蠢的主观术语(尽管有时很有趣)。我从未说过这是邪恶的,这就是为什么我不遵循这种方法。有人告诉我,我不使用分号是“邪恶的”。我告诉他们,他们实际上应该提出好的论据和/或更好地学习JavaScript :-)
我知道还有一个“应用”内置的javascript函数可以在调用方法时显式定义范围。这个会比较好吗?
问题apply/call在于您必须在函数调用时使用它们。如果其他人调用了您的方法之一,那将无济于事,因为this可能已经关闭了。这对于执行诸如jQuery样式的回调之类的操作最为有用,其中jQuerythis是回调的元素/项目,等等。
我喜欢避免成员上的“需要自我”,因此通常将所有成员函数提升为接收者(this)只是“流经”(通常是“预期”)的属性。
我的代码中的“私有”方法以“ _”开头,如果用户调用它们,它们就在它们上面。当使用原型方法创建对象时,这也更好(实际上是必需的)。但是,道格拉斯·克罗克福德(Douglas Crockford)不赞成我的这种“私有”方法,在某些情况下,查找链可能会由于注入意外的接收者而使您受挫:
在构造函数中使用“自我”绑定还可以锁定方法的查找链的上限(它不再是向上的多态!),这可能是正确的,也可能是不正确的。我认为通常是不正确的。
快乐的编码。
obj.member通常可以确保this正确(因为obj->this(obj)->this(obj)->...)。如果您在帖子中看到Crockford链接,您将看到private方法打破了模式,因为私有“方法”现在存储在构造函数中的变量中,因此不会在obj.member表单中调用。除非完成额外的工作,否则this它们将在它们内部抛出(就像this在调用时,函数的接收者一样obj)。
aelf是窗口对象-我会避免使用保留字,和使用var that = this或var _self = this
var self = false全局上下文,然后var self = this;在需要的地方添加方法。然后,如有疑问,请写信(self || this).method(...)。这是很糟糕的编码,但是感觉很好。
是的,这是标准方式。
Function.apply()并且Function.call()可以帮助,但并非总是如此。
考虑以下
function foo()
{
var self = this;
this.name = 'foo';
setTimeout( function()
{
alert( "Hi from " + self.name );
}, 1000 );
}
new foo();
如果您想这样做,但避免使用像selfand usecall()或apply()...这样的变量,那么...您可以看一下并开始尝试,但是很快就意识到您做不到。setTimeout()负责lambda的调用,因此您无法利用这些替代的调用样式。您仍然会最终创建一些中间变量来保存对该对象的引用。
setTimeout( (function() { alert( "Hi from " + this.name ); }).apply(this), 1000 ); }
这是保持正确绑定的标准方法吗?
没有关于JavaScript和类/实例系统的标准。您将必须选择自己喜欢的对象模型。这是指向背景资料的另一个链接;结论:没有结论。
通常var self= this;,在闭包中保留副本(*)与围绕闭包构建的对象模型齐头并进,闭包中包含每种方法的每个实例的副本。这是做事的有效方法。与原型(使用原型构建,使用this,apply()以及ECMAScript Fifth Editionbind()获取绑定方法)建立的对象模型相比,效率低一些,但通常工作量也少得多。
当您在同一代码中将两种样式混搭在一起时,可以算作“邪恶”。不幸的是,许多常见的JS代码都这样做(因为让我们面对现实,没有人真正理解JavaScript的奇异本机对象模型)。
(*:我通常使用;that而不是self;您可以使用任何您喜欢的变量名,但是self作为window指向窗口本身的成员已经有些模糊且完全没有意义了。)
在具有闭包的javascript和其他语言中,这可能是一件非常重要的事情。this方法中引用的对象实际上可以更改。一旦您设置self变量等于this,则自会可靠地保持到相关对象的引用,即使this后来点不同的东西。
与我们使用的许多其他语言相比,这是javascript的重要区别。我来自.Net,所以这种类型的东西一开始对我也很奇怪。
编辑:啊,好的,你知道的全部。(也许对其他人还是有帮助的。)我将补充说,“应用”(和“调用”)更多地是从“外部”使用的,这赋予了您要调用的函数的已知范围。一旦进入函数内部,您将进一步层叠到闭包中,该技术如下:
var self = this;
是更合适的方式(容易和清晰的)的方式来锚您的当前范围。
我认为,var self = this在所有方法中都应始终包含一个论点:人为因素。
经常需要它,以至于您杂乱无章地访问方法,this而其他人使用self用于相同的目的。如果将代码从一个移到另一个,突然会出现很多错误。
同时,self.foo当我不需要或添加时,我会因为心不在a而习惯性地写作var self = this。因此,我认为养成始终包括必要与否的习惯是有道理的。
唯一的麻烦是... this,self或者that代码上都是丑陋的痘痘,我有点讨厌它们。所以我觉得这是更好地避免使用委托方法在可能的情况,这样就可以尽量避免使用this,that或self绝大多数的时间,使用.bind(this)的时候,否则你可能诉诸self/that。很少在原型上使用委托实际上会为您节省大量内存。
这种方法的一个很好的副作用是,您不必在所有私有变量_前面加上,因为它们将是真正的私有,并且公共属性将由前导调用this.,从而使您的代码更具可读性。
正如bobince所说,var that = this更好是因为它不会遮挡window.self。 self = this听起来对我来说不太尴尬,但有时您会收到诸如之类的错误消息property myMethod not found on global,因为您忘记了这一self = this行。
我只想指出'self'等同于'window',请尝试将window === self输出到控制台。您应该将此模式与'that'或类似的变量名一起使用,避免使用'self',因为浏览器已在使用它(一个错误,您将自己创建一个全局变量)。即使听起来很奇怪,也最好使用“ that”作为名称,因为其他开发人员会立即知道您要在代码中完成的工作,避免使用非标准的变量名。我认为这是一个重要的注释,但仅在一个注释中提及,因此我想使其更明显。
6年后的今天,我有几件事要补充:
bind()现在已经足够普遍,可以在任何地方使用。我经常使用它作为替代。有时感觉更清晰。我还是偶尔用var self = this;。虽然。
箭头功能逐渐变得可行。语法短了一点,这很好,但是我认为杀手级功能实际上是默认情况下它们始终绑定到父作用域。
这个:
var self = this;
var foo = function(a) {
return self.b + a;
};
现在可以写成:
var foo = a => this.b + a;
这是箭头功能的“最乐观”用法,但非常好用。
简而言之,这没有什么错:
var self = this;
我喜欢。这是“自我”的解释。道格拉斯·克罗克福德(Douglas Crockford)对此有话要说。他指出,使用“ that”是惯例。如果您搜寻yui剧院并观看有关Javascript的视频,则可以免费观看Crockford 。
var that = this,老实说,我什至没有打扰到应用程序/调用,但现在我读到了有关这些方法的信息,谢谢您提出这个问题!