我发现自己需要:
var self = this;
在我的javascript'类'中很多。尽管通常这样做,但感觉有点不对劲。 我希望在这个问题中找到的是一个更好的方法来解决这个问题,或者是一个让我相信这一点的方法。
这是保持正确绑定的标准方法吗?我应该在任何地方标准化使用'self',除非我明确需要'this'。
编辑:我确切地知道为什么我需要这个,我只是想知道它是否有点邪恶,为什么。我知道在调用方法时还有'apply'内置的javascript函数来显式定义范围。它更好吗?
答案 0 :(得分:48)
正如其他人所说:这个“额外变量”是(在某种程度上)获得this
是一个特殊表达式的唯一方法,因此,不是变量,不受约束执行上下文/闭包。
然而,我认为你在问(或者我真正想要回答的)是:
是否应该将
var self = this
放在每个方法/构造函数的顶部?
虽然我尝试了一次,并且有同样的问题,但我不再使用这种方法了。现在我保留构造,以便在需要访问闭包时。对我而言,它增加了一点“嘿,这就是我真正想要的!”我的代码是语义的:
this -> this
和self -> this (but really that) in a closure
......虽然这种做法很常见,但感觉有些不对劲。我希望在这个问题中找到的是一个更好的方法来解决这个问题,或者是一个让我相信这一点的方法。
做对你感觉合适的事情。不要害怕尝试一种方法并稍后再切换(但请尽量在每个项目中保持一致: - )
这是保持正确绑定的标准方法吗?我应该在任何地方标准化使用'self',除非我明确需要'this'。
“self”是最常用的名称。如上所述,我更喜欢相反的方法 - 使用this
,除非需要闭包绑定。
..如果它被认为有点邪恶,为什么。
邪恶是一个愚蠢的主观术语(虽然有时很有趣)。我从来没有说过它是邪恶的,只是为什么我不遵循这个方法。有些人告诉我,因为不使用分号,我是“邪恶的”。我告诉他们他们实际上应该提出好的论据和/或更好地学习JavaScript: - )
我知道在调用方法时还有'apply'内置的javascript函数来显式定义范围。它更好吗?
apply/call
的问题是你必须在函数调用时使用它们。如果某人 else 调用您的某个方法,因为this
可能已经关闭,则无效。这对于jQuery样式的回调最有用,其中this
是回调的元素/项目等。
我喜欢在成员上避免“需要自我”,因此通常会将所有成员函数提升为接收者(this
)刚刚“流过”的属性,这通常是“as预期”。
我的代码中的“私有”方法以“_”开头,如果用户调用它们,那就是它们。当使用原型方法创建对象时,这也可以更好地工作(非常需要)。但是,Douglas Crockford disagrees采用了我的“私人”方法,有些情况下,查找链可能会通过注入意外的接收器来阻止你:
在构造函数中使用“self”绑定也会锁定方法的查找链的上限 (它不再是多态的!)可能是也可能不对。我认为这通常是不正确的。
快乐的编码。
答案 1 :(得分:17)
是的,这是标准方式。
Function.apply()
和Function.call()
可以提供帮助,但并非总是如此。
考虑以下
function foo()
{
var self = this;
this.name = 'foo';
setTimeout( function()
{
alert( "Hi from " + self.name );
}, 1000 );
}
new foo();
如果您想这样做,但要避免使用self
这样的变量,而是使用call()
或apply()
......那么......你看看它并开始尝试,但很快意识到你不能。 setTimeout()
负责调用lambda,使您无法利用这些备用调用样式。你最终还是会创建一些中间变量来保存对象的引用。
答案 2 :(得分:9)
这是保持正确绑定的标准方法吗?
没有标准,涉及JavaScript和类/实例系统。您将不得不选择您喜欢的对象模型。这是another link到背景资料;结论:没有结论。
通常在闭包中保留副本var self= this;
(*)与围绕闭包构建的对象模型一起使用每个方法的每个实例副本。这是一种有效的做事方式;效率稍低,但通常比替代方案少一点,一个围绕原型构建的对象模型,使用this
,apply()
和ECMAScript第五版的bind()
来获取绑定方法。 / p>
当你在同一个代码中使用两种风格的混搭时,可以将其视为“邪恶”。不幸的是,很多常见的JS代码都是这样做的(因为让我们面对它,没有人真的理解JavaScript奇特的原生对象模型)。
(*:我通常使用that
代替self
;您可以使用您喜欢的任何变量名称,但self
已经具有某种模糊且毫无意义的含义window
1}}指向窗口本身的成员。)
答案 3 :(得分:6)
刚刚遇到这个问题,因为我的同事沉迷于自我/变量,我想明白为什么......
我认为现在有更好的方式来处理这个:
function () {}.bind(this); // native
_.bind(function () {}, this); // lodash
$.proxy(function () {}, this); // jquery
答案 4 :(得分:3)
在javascript和closures的其他语言中,这可能是非常重要的事情。 this
在方法can actually change中引用的对象。将self
变量设置为this
后, self 将可靠地保留对相关对象的引用,即使this
稍后指向不同的对象
与我们工作的许多其他语言相比,这是javascript的一个重要区别。我来自.Net,所以这种类型的东西起初对我来说也很奇怪。
修改强>: 啊,好吧,你知道这一切。 (对于其他人来说可能仍然有帮助。)我将补充说,应用(和呼叫)更多是使用来自"外部",给予您调用特定范围的功能你已经知道了。一旦你进入一个函数并且你将要进一步级联到闭包中,该技术:
var self = this;
是支持当前范围的更合适的方式(简单和清除)。
答案 5 :(得分:2)
最有可能这样做是为了在范围即将发生变化时保持对this
的引用(在关闭的情况下)。我不知道我认为这本身就是一种不好的做法或模式,不是。你可以通过jQuery这样的库看到类似的东西,并且可以使用AJAX。
答案 6 :(得分:1)
我认为在每种方法中总是包括var self = this
是有争议的:人为因素。
为了达到同样的目的,您需要经常使用this
和其他人使用self
进行混搭。如果你将代码从一个移到另一个,突然间会出现一堆错误。
与此同时,当我不需要或添加self.foo
时,我会心不在焉地写出var self = this
的习惯。因此,我认为只要养成一种习惯,即始终包含它,需要与否。
唯一的麻烦是...... this
,self
或that
对你的代码来说都是一个丑陋的痘,我有点讨厌它们。所以我认为最好避免在可能的情况下使用委托方法,这样您就可以避免在绝大多数情况下使用this
,that
或self
,并使用.bind(this)
否则,您可能会诉诸self
/ that
。在原型上使用委托实际上是非常罕见的,无论如何都会为你节省大量的内存。
这种方法的一个很好的副作用是你不必用_
为所有私有变量添加前缀,因为它们将是真正的私有变量,公共属性将被前导{{1使代码更具可读性。
正如bobince所说,this.
更好,因为它不会影响var that = this
。 window.self
对我来说听起来不那么尴尬,但有时你会收到诸如self = this
之类的令人困惑的错误消息,因为你忘记了property myMethod not found on global
行。
答案 7 :(得分:1)
我只是想指出一下“自我”'相当于' window',尝试将窗口=== self输出到控制台。你应该使用这种模式''或类似变量名称的东西,避免使用' self'因为它已被浏览器使用(一个错误,你将自己创建一个全局变量)。 即使听起来很奇怪,最好还是使用'因为它的名字是因为其他开发人员会立即知道你在代码中想要完成什么,避免使用非标准变量名。 我相信这是一个重要的注释,但它只在一条评论中提到过,所以我想让它更加明显。
答案 8 :(得分:1)
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;
答案 9 :(得分:0)
我喜欢它。这是“自我” - 解释。 Douglas Crockford对此有一些说法。他说使用“那个”是惯例。你可以免费看到Crockford,如果你去了yui-theater并观看他关于Javascript的视频。