为什么 JavaScript 中没有隐式 this

发布于 2024-10-15 16:49:44 字数 368 浏览 6 评论 0原文

在 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

尐偏执 2024-10-22 16:49:44

Python 中也类似。原因很简单:您不能添加它,因为它与在外部作用域中搜索非局部变量的默认作用域规则冲突。这在静态类型语言中是可能的,因为 this 的成员在编译时是已知的。

如果这是一个动态决策,例如“x 引用 this.x if this.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 to this.x if this.x !== undefined and otherwise to the variable x" (or any other rule for this that is decided at runtime)? That's very dangerous, as it can shadow local variables based on what this happens to be, i.e. breaking perfectly valid code only for certain objects. Another issue: Should undeclaredVar = ... add a new instance attribute? If not, that would be an ugly asymmetry between implicit and explicit this. 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.

多孤肩上扛 2024-10-22 16:49:44

您必须显式指定“this”,因为“window”是隐式的,

代码

function SomeFunc(x) {
    y = x;
    return this;
}

function SomeFunc(x) {
    window.y = x;
    return this;
}

You have to explicitly specify "this" because "window" is implicit instead

Code

function SomeFunc(x) {
    y = x;
    return this;
}

Is the same as

function SomeFunc(x) {
    window.y = x;
    return this;
}
旧人 2024-10-22 16:49:44

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.

£噩梦荏苒 2024-10-22 16:49:44

每个函数对象都会引入一个新的命名空间,并用其参数、变量和内部函数声明填充它。如果 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.

习ぎ惯性依靠 2024-10-22 16:49:44

如果 x 隐含为 this.x,那么您将如何访问定义为名称 x 的变量?

function Frobber(x) { this.x = x; }
Frobber.prototype.frob = function() {
   var x = 'WHAT ABOUT ME';
   return x;
}

If x is implied to be this.x, how would you access variables defined as the name x?

function Frobber(x) { this.x = x; }
Frobber.prototype.frob = function() {
   var x = 'WHAT ABOUT ME';
   return x;
}
滥情哥ㄟ 2024-10-22 16:49:44

来自 JavaScript:好的部分 (函数 -- 调用 ):

JavaScript中有四种调用模式:方法调用模式、函数调用模式、构造函数调用模式和apply调用模式。

基本上,这些“模式”中的每一个都决定了 this 引用的定义方式。如果函数被定义为对象的方法,则 this 将引用父对象。如果函数不是对象的属性,则 this 指的是全局对象。如果使用new 关键字调用该函数(即作为构造函数),则this 引用新创建的对象。最后,如果您使用该函数的 apply() 方法this 的引用绑定到您指定的任何对象。

From JavaScript: The Good Parts (Functions -- Invocation):

There are four patterns of invocation in JavaScript: the method invocation pattern, the function invocation pattern, the constructor invocation pattern, and the apply invocation pattern.

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 the new keyword (i.e. as a constructor) then this refers to the newly created object. And finally, if you use the function's apply() method the reference of this is bound to whatever object you specify.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文