是var self = this; 一个不好的模式?

我发现自己需要:

var self = this; 

很多我的JavaScript'类'。 虽然这是通常的做法,但感觉有点不对劲。 在这个问题上我希望find的是处理这个问题的更好的方法,或者说服我相信这是相当好的。

这是保持正确绑定的标准方式吗? 我是否应该在任何地方使用“自我”来标准化,除非我明确需要“这个”。

编辑 :我确切地知道为什么我需要这个,我只是想知道如果它被认为有点邪恶,为什么。 我知道也有'应用'内置JavaScript函数来显式定义调用方法的范围。 好点吗?

正如其他人所说:这个“额外的variables”是(在某种程度上)唯一的方式来得到这个事实, this是一个特殊的expression,因此,不是一个variables,不被绑定在执行上下文中。

但是,我想你所问的(或我真正想要回答的)是:

应该把var self = this放在每个方法/构造函数的顶部吗?

概要

虽然我尝试了一次,并有同样的问题,我不再使用这种方法。 现在我保留构造,当我需要在封闭访问。 对我来说,它增加了一点“嘿,这是我真正想要的!” 语义到我的代码:

this -> thisself -> this (but really that) in a closure

问题点菜:

…虽然这是通常做的,但感觉有点不对劲。 在这个问题上我希望find的是处理这个问题的更好的方法,或者说服我相信这是相当好的。

做你觉得正确的事。 不要害怕尝试一种方法,稍后再切换(但是请在每个项目中保持一致:-)

这是保持正确绑定的标准方式吗? 我是否应该在任何地方使用“自我”来标准化,除非我明确需要“这个”。

“自我”是最常用的名字。 如上所述,我更喜欢相反的方法 – 除非需要封闭绑定时才使用this方法。

如果它被认为有点邪恶,为什么。

邪恶是一个愚蠢的主观术语(尽pipe有趣)。 我从来没有说过这是邪恶的,为什么我不遵循这个方法。 有人告诉我,因为没有使用分号,我是“邪恶的”。 我告诉他们,他们应该提出很好的论点和/或更好地学习JavaScript 🙂

我知道也有'应用'内置JavaScript函数来显式定义调用方法的范围。 好点吗?

apply/call的问题是你必须在函数调用的时候使用它们。 如果有人打电话给你的方法之一, this可能已经closures,这将无济于事。 这对于做thiscallback的元素/项目等jQuery风格的callback是非常有用的。

另外…

喜欢避免对成员“需要自我” ,因此普遍地将所有成员函数提升到接收者( this )刚才“stream经”的属性,这通常是“预期的”。

我的代码中的“私有”方法以“_”开始,如果用户调用它们,就是在它们上面。 当使用原型方法创build对象时,这也会更好(实际上是必需的)。 然而, 道格拉斯·克罗克福德 ( Douglas Crockford)不同意我的这种“私人”的方法,在某些情况下,查找链可能会通过注入一个意外的接收者来阻挠你:

在构造函数中使用“自我”边界也locking了一个方法的查找链的上限 (它不再是多态的向上!),这可能是也可能不是正确的。 我认为这通常是不正确的。

快乐的编码。

是的,这是标准的方式。

Function.apply()Function.call()可以帮助,但不总是。

考虑以下几点

 function foo() { var self = this; this.name = 'foo'; setTimeout( function() { alert( "Hi from " + self.name ); }, 1000 ); } new foo(); 

如果你想这样做,但要避免使用像self这样的variables,而应该使用call()apply()来代替…呃…你看它并开始尝试,但很快就意识到你不能。 setTimeout()负责调用lambda,使您无法利用这些替代调用样式。 您仍然会创build一些中间variables来保存对象的引用。

这是保持正确绑定的标准方式吗?

关于JavaScript和类/实例系统,没有标准。 你将不得不select你喜欢什么样的对象模型。 这是另一个背景的链接 ; 结论:没有结论。

通常保留副本var self= this; (*)与一个围绕着闭包的对象模型一起使用,并且每个方法的每个实例都有一个拷贝。 这是一个有效的做事方式; 效率稍低一点,但是通常比替代方法要less一些工作,一个围绕原型构build的对象模型,使用apply()和ECMAScript第五版的bind()来获得绑定方法。

更糟糕的是,当你在同一个代码中混合使用这两种风格的时候,可能会被认为是“邪恶”。 不幸的是,很多常见的JS代码都是这样做的(因为让我们面对它,没有人真正理解JavaScript奇怪的本地对象模型)。

(*:我通常使用that来代替self ;你可以使用任何你喜欢的variables名,但是作为指向窗口本身的window成员, self已经有一些有点模糊和毫无意义的含义。

刚刚遇到这个问题,因为我的同事沉迷于自我/变数,我想明白为什么…

我认为现在有更好的方法来处理这个问题:

 function () {}.bind(this); // native _.bind(function () {}, this); // lodash $.proxy(function () {}, this); // jquery 

在JavaScript和其他语言与闭包 ,这可能是一个非常重要的事情。 在一个方法中引用的对象实际上可以改变 。 一旦将selfvariables设置为等this ,那么即使后面指向不同的东西, 自己也会可靠地保持对所讨论对象的引用。

与我们工作的许多其他语言相比,这是一个重要的区别。我来自.Net,所以这种types的东西起初对我来说似乎很奇怪。

编辑 :啊,好吧,你知道这一切。 (也许对其他人有帮助)。我会补充一点,Apply(和Call)更适合从“外部”使用,给出一个你正在调用一个你已经知道的特定范围的函数。 一旦你进入了一个函数,并且你将要进一步级联到闭包,这个技巧:

  var self = this; 

是更合适的方式( 简单 明了 )来锚定当前范围。

这很可能是在范围即将发生变化(如果是封闭的情况下)的情况下保持this的引用。 我不知道我会认为这是一个不好的做法或模式本身,不。 像jQuery这样的库,以及与AJAX一起工作的很多东西,你会看到很多类似的东西。

我认为在每种方法中总是包括var self = this是人为因素。

通常情况下,你需要经常使用self的方法访问this方法,而其他的方法则需要使用self的方法。 如果你把代码从一个移到另一个,突然你会遇到一堆错误。

同时,当我不需要或者添加一个var self = this时候,我发现自己心不在焉地写出self.foo出于习惯。 所以我觉得只要养成一个习惯就可以了。

唯一的麻烦是… this ,我self ,或者that对你的代码来说都是一个丑陋的痘痘,我有种憎恨他们。 所以我认为最好避免在可能的情况下使用委托方法,这样可以避免在绝大多数情况下使用thisthat self ,并且在使用.bind(this)时候可能会使用self / that 。 在原型上使用委托实际上将会为您节省大量的内存是非常罕见的。

这种方法的一个很好的副作用是,你不必用_作为你所有的私有variables的前缀,因为它们将是真正的私有的,公共属性将被领导this.叫出来this. ,使您的代码更具可读性。

正如bobince所说, var that = this比较好,因为它不会影响window.selfself = this对我来说听起来不太尴尬,但是有时候你会得到一些令人困惑的错误信息,例如property myMethod not found on global ,因为你忘记了self = this行。

我只想指出,'自我'相当于'窗口',尝试输出窗口===自我的控制台。 你应该使用这个模式作为一个variables名称,避免使用“自我”,因为它已经被浏览器使用(一个错误,你会创build一个全局variables)。 尽pipe这听起来很奇怪,但最好使用“那个”作为它的名字,因为其他开发者会立即知道你在代码中想要完成什么,避免使用非标准的variables名。 我相信这是一个重要的说明,但只是在一个评论中提到,所以我想让它更加明显。

6年过去了,我还有一些东西需要补充:

bind()现在已经足够普遍到处使用了。 我经常使用它作为替代。 有时感觉更清楚。 我仍然有时使用var self = this; 。 虽然。

箭头function正在慢慢变得可行。 语法有点短,这是不错的,但我认为杀手function的确是默认情况下,他们总是绑定到父范围。

这个:

 var self = this; var foo = function(a) { return self.b + a; }; 

现在可以写成:

 var foo = a => this.b + a; 

这是箭头函数的“最乐观”的用法,但是非常的甜美。

最后,没有什么错:

 var self = this; 

我喜欢。 这是“自我”的解释。 道格拉斯·克罗克福德(Douglas Crockford)有些话要说。 他表示使用“that”是惯例。 你可以看到克罗克福德免费,如果你scoot到yui-theatre和观看他的video关于Javascript 。