Javascript 是 var self = this; 一个不好的模式?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4371333/
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
Is var self = this; a bad pattern?
提问by Evert
I find myself needing:
我发现自己需要:
var self = this;
a lot within my javascript 'classes'. Although this is commonly done, it feels a bit wrong. What I'm hoping to find in this question is a better way to deal with this, or a something to convince me this is quite alright.
在我的 javascript '类' 中有很多。虽然这是常用的做法,但感觉有点不对。我希望在这个问题中找到一种更好的方法来解决这个问题,或者让我相信这是很好的。
Is this the standard way to keep the correct bindings around? Should I standardize on using 'self' everywhere, unless i explicitly need 'this'.
这是保持正确绑定的标准方法吗?除非我明确需要“this”,否则我是否应该标准化在任何地方使用“self”。
edit: I know exactly why I need this, I'm just wondering if it's considered a bit evil and why. I'm aware there's also the 'apply' built-in javascript function to explicitly define scope when calling a method. Is it better?
编辑:我确切地知道我为什么需要这个,我只是想知道它是否被认为有点邪恶以及为什么。我知道还有“应用”内置 javascript 函数可以在调用方法时显式定义范围。这个会比较好吗?
采纳答案by Evert
As others have said: This "extra variable" is (at some level) the only way to get about the fact that this
is a special expression and thus, being not a variable, is not bound in an execution context/closure.
正如其他人所说:这个“额外变量”是(在某种程度上)获得this
特殊表达式这一事实的唯一方法,因此,它不是变量,不受执行上下文/闭包的约束。
However, what I think you are asking (or what I really want to answer) is:
但是,我认为您要问的(或我真正想回答的)是:
Should one put
var self = this
at the top of every method/constructor?
应该放在
var self = this
每个方法/构造函数的顶部吗?
Summary
概括
While I tried this once, and had the same question, I no longer use this approach. Now I reserve the construct for when I need access in a closure. To me it adds a little "hey, this is what I really want!" semantic to my code:
虽然我试过一次,并有同样的问题,但我不再使用这种方法。现在,我保留该构造以供需要在闭包中访问时使用。对我来说,它增加了一点“嘿,这就是我真正想要的!” 我的代码的语义:
this -> this
and self -> this (but really that) in a closure
this -> this
和 self -> this (but really that) in a closure
Questions ala carte:
单点问题:
...Although this is commonly done, it feels a bit wrong. What I'm hoping to find in this question is a better way to deal with this, or a something to convince me this is quite alright.
……虽然这是常用的做法,但感觉有点不对劲。我希望在这个问题中找到一种更好的方法来解决这个问题,或者让我相信这是很好的。
Do what feels right to you. Don't be afraid to try one method and switch back later (but please try to remain consistent within each project :-)
做你认为正确的事情。不要害怕尝试一种方法并稍后切换回来(但请尝试在每个项目中保持一致:-)
Is this the standard way to keep the correct bindings around? Should I standardize on using 'self' everywhere, unless i explicitly need 'this'.
这是保持正确绑定的标准方法吗?除非我明确需要“this”,否则我是否应该标准化在任何地方使用“self”。
"self" is the most common name used. As per above, I prefer the opposite approach -- to use this
except when a closure binding is required.
“self”是最常用的名称。如上所述,我更喜欢相反的方法——this
除非需要闭包绑定,否则使用。
..if it's considered a bit evil and why.
..如果它被认为有点邪恶以及为什么。
Evil is a silly subjective term (albeit fun sometimes). I've never said it was evil, just why I do not follow the approach. Some people tell me I am "evil" for not using semi-colons. I tell them they should actually come up with good arguments and/or learn JavaScript better :-)
邪恶是一个愚蠢的主观术语(尽管有时很有趣)。我从来没有说过这是邪恶的,这就是为什么我不遵循这种方法。有些人告诉我,我不使用分号是“邪恶的”。我告诉他们他们应该提出好的论据和/或更好地学习 JavaScript :-)
I'm aware there's also the 'apply' built-in javascript function to explicitly define scope when calling a method. Is it better?
我知道还有“应用”内置 javascript 函数可以在调用方法时显式定义范围。这个会比较好吗?
The problem with apply/call
is that you must use them at point of the function invocation. It won't help if someone elsecalls one of your methods as the this
may already be off. It's most useful for doing things like the jQuery-style callbacks where the this
is the element/item of the callback, etc.
问题apply/call
在于您必须在函数调用时使用它们。如果其他人调用您的方法之一,这将无济于事,因为它this
可能已经关闭。它对于执行诸如 jQuery 样式的回调之类的事情最有用,其中this
是回调的元素/项目等。
As an aside...
作为旁白...
I like to avoid "needing self" on membersand thus generally promote all member functions to properties where the receiver (this
) just "flows through", which is normally "as expected".
我喜欢避免成员“需要自我”,因此通常将所有成员函数提升到接收者 ( this
) 只是“流经”的属性,这通常是“如预期的”。
The "private" methods in my code begin with a "_" and if the user calls them, that's on them. This also works better (is required, really) when using the prototype approach to object creation. However, Douglas Crockford disagreeswith this "private" approach of mine and there are some cases where the look-up chain may thwart you by injecting an unexpected receiver:
我的代码中的“私有”方法以“_”开头,如果用户调用它们,那就是它们。当使用原型方法创建对象时,这也更有效(实际上是必需的)。但是,Douglas Crockford 不同意我的这种“私有”方法,并且在某些情况下,查找链可能会通过注入意外接收器来阻止您:
Using the "self" bound in the constructor also locks the upper limit of the look-up chain for a method(it is no longer polymorphic upward!) which may or may not be correct. I think it's normally incorrect.
在构造函数中使用“self”绑定也会锁定一个方法的查找链的上限(它不再是向上多态的!),这可能正确也可能不正确。我认为这通常是不正确的。
Happy coding.
快乐编码。
回答by Peter Bailey
Yes, this is the standard way.
是的,这是标准方式。
Function.apply()
and Function.call()
can help, but not always.
Function.apply()
并且Function.call()
可以提供帮助,但并非总是如此。
Consider the following
考虑以下
function foo()
{
var self = this;
this.name = 'foo';
setTimeout( function()
{
alert( "Hi from " + self.name );
}, 1000 );
}
new foo();
If you wanted to do this but avoid the usage of a variable like self
and use call()
or apply()
instead... well... you look at it and start to try, but soon realize you just can't. setTimeout()
is responsible for the invocation of the lambda, making it impossible for you to leverage these alternate invocation styles. You'd still end up creating some intermediary variable to hold a reference to the object.
如果你想这样做但避免使用像self
and use call()
or之类的变量apply()
......好吧......你看着它并开始尝试,但很快意识到你不能。setTimeout()
负责 lambda 的调用,使您无法利用这些替代调用样式。您最终仍会创建一些中间变量来保存对对象的引用。
回答by bobince
Is this the standard way to keep the correct bindings around?
这是保持正确绑定的标准方法吗?
There is no standard, where JavaScript and class/instance systems are concerned. You will have to choose what kind of object model you prefer. Here's another linkto a backgrounder; conclusion: there is no conlusion.
没有关于 JavaScript 和类/实例系统的标准。您必须选择您喜欢的对象模型类型。这是背景知识的另一个链接;结论:没有结论。
Typically keeping a copy var self= this;
(*) in a closure goes hand-in-hand with an object model built around closures with per-instance copies of each method. That's a valid way of doing things; a bit less efficient, but also typically a bit less work than the alternative, an object model built around prototyping, using this
, apply()
and ECMAScript Fifth Edition's bind()
to get bound methods.
通常var self= this;
在闭包中保留一个副本(*) 与围绕闭包构建的对象模型密切相关,每个方法的每个实例副本。这是一种有效的做事方式;少了几分效率高,而且通常少一点的工作比选择,对象模型构建原型左右,使用this
,apply()
和ECMAScript第五版的bind()
获得绑定方法。
What could be counted more as ‘evil' is when you have a mish-mash of both styles in the same code. Unfortunately a lot of common JS code does this (because let's face it, no-one reallyunderstands JavaScript's bizarre native object model).
当您在同一代码中混合了两种风格时,更可以算作“邪恶”。不幸的是,很多常见的 JS 代码都是这样做的(因为让我们面对现实,没有人真正理解 JavaScript 奇异的原生对象模型)。
(*: I typically use that
instead of self
; you can use any variable name you like, but self
already has an somewhat obscure and completely pointless meaning as a window
member that points to the window itself.)
(*:我通常使用that
而不是self
; 你可以使用任何你喜欢的变量名,但self
作为window
指向窗口本身的成员已经有一个有点模糊和完全没有意义的意义。)
回答by AlexanderB
Just came across this question because my coworkers addicted to self/that variables and I wanted to understand why...
刚刚遇到这个问题是因为我的同事沉迷于自我/那个变量,我想了解为什么......
I think there is a better way to deal with thisin nowdays:
我认为现在有更好的方法来处理这个问题:
function () {}.bind(this); // native
_.bind(function () {}, this); // lodash
$.proxy(function () {}, this); // jquery
回答by Patrick Karcher
In javascript and other languages with closures, this can be a very important thing to do. The object that this
refers to in a method can actually change. Once you set your self
variable equal to this
, then selfwill reliably remain a reference to the object in question, even if this
later points to something different.
在 javascript 和其他带有闭包的语言中,这可能是一件非常重要的事情。this
在方法中引用的对象实际上可以改变。一旦您将self
变量设置为等于this
,则self将可靠地保持对相关对象的引用,即使this
稍后指向不同的对象。
This is an important difference in javascript compared to many other languages we work in. I'm coming from .Net, so this type of thing seemed strange to me at first too.
与我们使用的许多其他语言相比,这是 javascript 的一个重要区别。我来自 .Net,所以这种类型的事情起初对我来说也很奇怪。
Edit: Ah, okay, you know all that. (maybe still helpful for someone else.) I'll add that Apply (and Call) are more for using from "the outside", giving to a function you're calling a specific scope that you already know about. Once you're inside a function and you're about to cascade further down into closures, the technique:
编辑:啊,好吧,你知道这一切。(可能对其他人仍然有帮助。)我要补充一点,Apply(和 Call)更适合从“外部”使用,为您正在调用的函数提供您已经知道的特定范围。一旦你进入一个函数并且你将进一步向下级联到闭包中,该技术:
var self = this;
is the more appropriate way (easyand clear) way to anchor your currentscope.
是更合适的方式(容易和清晰的)的方式来锚您的当前范围。
回答by g.d.d.c
Most likely this is done as a way to maintain a reference to this
when the scope is about to change (in the case of a closure). I don't know that I'd consider it a bad practice or pattern in and of itself, no. You see similar things a lot with libraries like jQuery and a great deal with working with AJAX.
这样做很可能是为了维护this
对范围即将发生变化的引用(在闭包的情况下)。我不知道我会认为它本身是一种不好的做法或模式,不。您会在 jQuery 之类的库中看到很多类似的东西,并且在大量使用 AJAX 时也会看到类似的东西。
回答by Evert
It's 6 years later, and I have some things to add myself:
6 年过去了,我有一些事情要补充:
bind()
is now common enough to be used everywhere. I use it often as an alternative. Sometimes it feels clearer. I still on occasion use var self = this;
. though.
bind()
现在已经足够普遍,可以在任何地方使用。我经常使用它作为替代。有时感觉更清晰。我仍然偶尔使用var self = this;
. 尽管。
Arrow functions slowly are becoming viable for usage. The syntax is a bit shorter which is nice, but I think the killer feature really is that by default they always bind to the parent scope.
箭头函数逐渐变得可行。语法有点短,这很好,但我认为杀手级功能确实是默认情况下它们总是绑定到父作用域。
This:
这个:
var self = this;
var foo = function(a) {
return self.b + a;
};
Can now be written as :
现在可以写成:
var foo = a => this.b + a;
This is the 'most optimistic' usage of arrow functions, but it's pretty sweet.
这是箭头函数的“最乐观”用法,但它非常可爱。
And just to concluse, there's nothing wrong with:
总结一下,没有任何问题:
var self = this;
回答by John Starr Dewar
I think there's an argument to be made for always including var self = this
in every method: human factors.
我认为有一个论点始终包括var self = this
在每种方法中:人为因素。
It's needed often enough that you wind up having a mishmash of methods accessing this
and others using self
for the same purpose. If you move code from one to the other, suddenly you get a bunch of errors.
它经常需要,以至于您最终将访问的方法this
和其他人self
用于同一目的的方法混为一谈。如果您将代码从一个移动到另一个,您会突然收到一堆错误。
At the same time, I catch myself absent-mindedly writing self.foo
out of habit when I haven't needed or added a var self = this
. So I think it could make sense to just make a habit of always including it, needed or not.
同时,self.foo
当我不需要或添加var self = this
. 所以我认为养成总是包含它的习惯是有意义的,无论是否需要。
The only trouble is... this
, self
, or that
are all an ugly pox on your code and I kind of hate them all. So I think it is better to avoid using delegated methods where possible so that you can avoid using this
, that
or self
the vast majority of the time, and use .bind(this)
when you might otherwise resort to self
/that
. It's very rare that using delegates on the prototype is actually going to save you any substantial amount of memory anyway.
唯一的麻烦是... this
, self
, 或者that
都是你代码上的丑陋痘痘,我有点讨厌它们。所以我认为最好尽可能避免使用委托方法,这样您就可以避免使用this
,that
或者self
在绝大多数情况下,并.bind(this)
在您可能求助于self
/ 时使用that
。无论如何,在原型上使用委托实际上会为您节省大量内存是非常罕见的。
A nice side effect of that approach is that you don't have to prefix all your private variables with _
, as they will be truly private and the public properties will be called out by the leading this.
, making your code more readable.
这种方法的一个很好的副作用是您不必为所有私有变量加上前缀_
,因为它们将是真正私有的,并且公共属性将由前导调用this.
,从而使您的代码更具可读性。
As bobince said, var that = this
is better because it doesn't shadow window.self
. self = this
sounds less awkward to me, but sometimes you get confusing error messages like property myMethod not found on global
, because you forgot the self = this
line.
正如 bobince 所说,var that = this
更好,因为它没有阴影window.self
。 self = this
对我来说听起来不那么尴尬,但有时您会收到诸如 之类的令人困惑的错误消息property myMethod not found on global
,因为您忘记了该self = this
行。
回答by Goran Vasic
I just want to point out that 'self' is equivalent to 'window', try outputting window === self to the console. You should use this pattern with 'that' or something similar as a variable name, avoid using 'self' since it is already in use by the browser (one mistake and you will create yourself a global variable). Even though it sounds weird, it is better to use 'that' for its name because other developers will immediately know what you were trying to accomplish in your code, avoid using nonstandard variable names. I believe that this is an important note, but it was only mentioned in one comment, so I wanted to make it more visible.
我只想指出 'self' 等价于 'window',尝试将 window === self 输出到控制台。您应该将此模式与 'that' 或类似变量名的名称一起使用,避免使用 'self',因为浏览器已经在使用它(一个错误,您将为自己创建一个全局变量)。尽管听起来很奇怪,但最好使用“that”作为其名称,因为其他开发人员会立即知道您要在代码中完成什么,避免使用非标准变量名。我相信这是一个重要的说明,但只在一个评论中提到过,所以我想让它更显眼。
回答by Phluks
I like it. It is "self"-explanatory. Douglas Crockford has some things to say about this. He states that using "that" is convention. You can see Crockford for free if you scoot over to yui-theater and watch hes videos about Javascript.
我喜欢。它是“自我”解释的。道格拉斯·克罗克福德对此有一些话要说。他指出使用“那个”是惯例。如果您快速前往 yui-theater 并观看有关Javascript 的视频,则可以免费观看 Crockford 。