为什么JavaScript中没有隐含的内容

时间:2011-02-02 15:01:32

标签: javascript language-design

在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属性不会自动生效?我认为这个设计决定必须有理由。

6 个答案:

答案 0 :(得分:11)

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

如果做出动态决定,例如“x如果this.x引用this.x !== undefined,则引用变量x”(或任何其他规则)为此,这是在运行时决定的)?这是非常危险的,因为它可以根据this恰好是什么来影响局部变量,即仅针对某些对象破坏完全有效的代码。另一个问题:undeclaredVar = ...应该添加新的实例属性吗?如果不是,那将是隐式和显式this之间的丑陋不对称。如果它 创建一个实例属性,你就失去了从内部函数设置全局和闭包变量的能力 - 不是太多的损失,很多人会说;但JS设计者似乎没有想到,因为他们选择全局范围作为默认值。

制作“临时变量”阴影实例属性会不那么危险,但是如果深度嵌套的范围充满了大量的名称,那么在大多数情况下你最终会被迫使用this. - 所以净胜利。为此,和/或出于其他原因,设计师认为捷径是不可行的。

答案 1 :(得分:2)

Javascript中“this”指的是完全一个如何调用当前函数的函数。

如果它被称为方法(即使用。运算符),那么'this'将被设置为点之前的对象。

如果它被称为简单函数,那么'this'将是全局对象(通常是窗口)。

IIRC如果你使用Function.call,你可以明确地设置它。

Javascript是一种OO语言,但有类,并且(严格地说)没有方法。

答案 2 :(得分:1)

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

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

答案 3 :(得分:1)

您必须明确指定“this”,因为“window”是隐含的

代码

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

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

答案 4 :(得分:1)

每个函数对象引入一个新的命名空间,并用它的参数,变量和内部函数声明来填充它。如果要将this对象的所有属性注入到同一名称空间中,则名称将发生冲突。

要防止此冲突,您必须明确确保每个参数名称,局部变量名称或函数声明名称与this引用的对象的任何属性不同。

由于您可以动态地向对象添加新属性,因此您还必须确保添加的任何新属性不会与每个对象方法中的所有参数,变量......发生冲突。

这几乎是不可能处理的。

答案 5 :(得分:0)

来自JavaScript: The Good PartsFunctions -- Invocation):

  

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

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