为什么 JavaScript 中没有隐式 this
在 JavaScript 中,访问其属性时必须始终显式声明 this
。例如:
function Frobber(x) {
this.x = x;
return this;
}
Frobber.prototype.frob = function () {
// wrong:
return x * x;
// right:
return this.x * this.x;
}
我知道我可以使用 with(this)
(它已被弃用并且通常不受欢迎),但为什么 this
的属性不会自动进入作用域?我认为这个设计决定一定是有原因的。
In JavaScript, this
must always be stated explicitly when accessing its properties. For example:
function Frobber(x) {
this.x = x;
return this;
}
Frobber.prototype.frob = function () {
// wrong:
return x * x;
// right:
return this.x * this.x;
}
I'm aware I can use with(this)
(which is deprecated and generally frowned upon), but why aren't properties of this
in scope automatically? I'm thinking there must be a reason for this design decision.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
Python 中也类似。原因很简单:您不能添加它,因为它与在外部作用域中搜索非局部变量的默认作用域规则冲突。这在静态类型语言中是可能的,因为
this
的成员在编译时是已知的。如果这是一个动态决策,例如“
x
引用this.x
ifthis.x !== undefined
”,否则会怎么样?到变量x
”(或在运行时决定的任何其他规则)?这是非常危险的,因为它可以根据this
发生的情况来隐藏局部变量,即仅破坏某些对象的完全有效的代码。另一个问题:undeclaredVar = ...
是否应该添加新的实例属性?如果不是,这将是隐式和显式this
之间丑陋的不对称。如果它确实创建了一个实例属性,那么您将失去从函数内部设置全局变量和闭包变量的能力 - 许多人会说,损失并不算太大;但 JS 设计者似乎另有想法,因为他们默认选择全局作用域。制作“临时变量”影子实例属性的危险性较小,但由于深度嵌套的作用域充满了许多名称,在大多数情况下,您可能最终会被迫使用
this.
- 所以更少净胜。为此,和/或可能由于其他原因,设计者认为捷径不可行。It's similar in Python. The reason is quite simple: You cannot add this, because it clashes with the default scoping rule of searching for non-local variables in the outer scopes. It's possible in statically-typed languages, because the members of the
this
are known at compile-time.And what if the made it a dynamic decision, such as "
x
refers tothis.x
ifthis.x !== undefined
and otherwise to the variablex
" (or any other rule for this that is decided at runtime)? That's very dangerous, as it can shadow local variables based on whatthis
happens to be, i.e. breaking perfectly valid code only for certain objects. Another issue: ShouldundeclaredVar = ...
add a new instance attribute? If not, that would be an ugly asymmetry between implicit and explicitthis
. If it does create an instance attribute, you'd lose the ability to set global and closure variable from inside functions - not too much of a loss, many would say; but the JS designers seem to have thought otherwise, as they chose global scope as default.Making "casual variables" shadow instance attributes would be less dangerous, but with deeply nested scopes filled with lots of names, you'd propably end up being forced to use
this.
in most cases - so less of a net win. For this, and/or propably for other reasons, the designers deemed a shortcut infeasible.您必须显式指定“this”,因为“window”是隐式的,
代码
与
You have to explicitly specify "this" because "window" is implicit instead
Code
Is the same as
Javascript 中的“this”完全是指当前函数如何被调用的函数。
如果它作为方法调用(即使用 . 运算符),则“this”将设置为点之前的对象。
如果它作为一个简单函数调用,那么“this”将是全局对象(通常是窗口)。
IIRC 如果您使用 Function.call,则可以显式设置它。
Javascript 是一种面向对象语言,但没有有类,并且(严格地)没有方法。
What "this" refers to in Javascript is wholly a function of how the current function has been called.
If it is called as a method (i.e. with the . operator) then 'this' will be set to the object before the dot.
If it is called as a simple function, then 'this' will be the global object (usually the window).
IIRC if you use Function.call, you can set it explicitly.
Javascript is an OO language but does not have classes, and does not (strictly) have methods.
每个函数对象都会引入一个新的命名空间,并用其参数、变量和内部函数声明填充它。如果
this
对象的所有属性都被注入到同一个命名空间中,则名称会发生冲突。为了防止这种冲突,您必须显式确保每个参数名称、局部变量名称或函数声明名称与
this
引用的对象的任何属性都不相同。由于您可以动态地向对象添加新属性,因此您还必须确保添加的任何新属性不会与每个对象方法中的所有这些参数、变量等发生冲突。
这几乎是不可能处理的。
Each function object introduces a new namespace and populates it with its parameters, variables and inner function declarations. If all the properties of the
this
object were to be injected into this same namespace, the names would collide.To prevent this collision, you would have to explicitly make sure that each parameter name, local variable name or function declaration name is not the same as any of the properties of the object that is referenced by
this
.Since you can dynamically add new properties to an object, you would also have to make sure that any new property that you add, does not collide with all those parameters, variables,... in each of the objects methods.
This would be nearly impossible to deal with.
如果
x
隐含为this.x
,那么您将如何访问定义为名称x
的变量?If
x
is implied to bethis.x
, how would you access variables defined as the namex
?来自 JavaScript:好的部分 (函数 -- 调用 ):
基本上,这些“模式”中的每一个都决定了
this
引用的定义方式。如果函数被定义为对象的方法,则this
将引用父对象。如果函数不是对象的属性,则this
指的是全局对象。如果使用new
关键字调用该函数(即作为构造函数),则this
引用新创建的对象。最后,如果您使用该函数的 apply() 方法this
的引用绑定到您指定的任何对象。From JavaScript: The Good Parts (Functions -- Invocation):
Basically, each of these "patterns" determine how the
this
reference is defined. If a function is defined as a method of an object,this
will refer to the parent object. If the function is not a property of an object,this
refers to the global object. If the function is invoked with thenew
keyword (i.e. as a constructor) thenthis
refers to the newly created object. And finally, if you use the function's apply() method the reference ofthis
is bound to whatever object you specify.