“这个”作为范围限制器?

时间:2014-07-16 14:30:12

标签: javascript

我试图理解“这个”,我所看到的一切都是关于背景的。这让我想到的是“这个”是一个范围限制器。它确保使用适当的范围引用变量,主要是通过将变量保持在“本地”范围内,并使它们远离运行代码的位置。

我的问题是:这是正确的吗?我尝试使用我想要的概念进行搜索,但是那些结果非常糟糕。 “这个”有很多细微之处,从我所做的阅读中,我觉得这比我所看到的更好,但我想确保我的思维正确。

1 个答案:

答案 0 :(得分:3)

this和变量范围是不同的概念。变量范围是指可以从应用程序中的哪个位置访问哪些变量。仅仅因为你在某个地方写了var foo 并不意味着你可以从整个代码库中的到处访问它。在Javascript中,每个function引入了一个新的范围,范围以内部函数可以访问外部函数范围的方式嵌套,但反之亦然。

另一方面,

this只是对“当前”对象的“魔术”引用。也许首先在其他经典语言的背景下解释这个想法是有帮助的:

class Foo {

    protected $bar;

    public function baz() {
        echo $this->bar;
    }

}

在PHP中,magic关键字$this引用当前对象实例。每次调用new Foo时,都会创建此类的新实例。每次调用$foo->baz()时,都会执行相同的函数,但$this设置为相应的对象实例,因此每个对象实例都可以访问自己的数据。

在Python中,这实际上更加明确:

class Foo:

    def baz(self):
        print self.bar

Python没有magic关键字来引用当前对象实例。相反,对对象的每个方法调用都会将当前对象显式传递为第一个参数。这通常命名为self。如果Python对你来说太陌生了,PHP语法中的上述内容将是:

class Foo {

    public function baz($this) {
        echo $this->bar;
    }

}

从技术上讲,这些类中的函数并不真正“属于”任何“类”。它们只是功能。您只需要某些方法让这些函数能够引用多态对象,以使它们成为实例方法。举个例子:

function baz($obj) {
    echo $obj->baz;
}

这与上面的类方法完全相同,区别在于$obj被明确注入而不是$this被神奇地“存在”。

Javascript具有相同的功能,除了{em>每个函数(不仅仅是“类”函数)中this可用,并且对象this指向的对象可以自由在运行时更改。 this只是一个指向对象的魔术关键字,句号。

function Foo() {
    this.bar = null;

    this.baz = function () {
        console.log(this.bar);
    }
}

foo.baz()等对象上调用常规函数时,this通常会引用foo内的baz();虽然它真的没有:

foo.baz.apply(someOtherObj);

这会使用foo.baz函数并在将this内的baz关键字设置为someOtherObj时调用它。如果愿意,它可以自由地将函数与另一个对象实例重新关联。但这只是因为首先将函数“绑定”到对象的唯一因素是this关键字。无论console.log(this.bar)指的是什么,该函数仍然只会this.bar


更完整的例子:

function Foo() {
    this.bar = 'baz';
}

Foo.prototype.speak = function () {
    alert(this.bar);
};

var o = new Foo();
o.speak();    // alerts 'baz'
alert(o.bar); // also alerts 'baz'

var o2 = { bar : 42 };
o.speak.apply(o2);  // alerts 42

如您所见,this并非限制任何内容的范围。这里发生了什么?

  1. 使用Foo调用new Foo()构造函数。 new只是创建一个新对象,并执行Foo()并将this设置为此新对象。基本上是:

    var tmp = {}; // tmp does not *actually* exist,
                  // that's more or less what `new` does behind the scenes
    Foo.apply(tmp);
    
  2. Foo构造函数指定该新对象的bar属性。

    tmp.bar = 'baz';
    
  3. 新对象已分配到o

    var o = tmp;
    
  4. o.speak()是通过其prototype绑定到该对象的函数。将其称为o.speak()this内的speak()指的是o对象。由于该对象具有属性bar,因此可以使用。

  5. 请注意,也可以执行alert(o.bar).bar属性最初设置在this,然后this变为o。因此o具有属性.bar,它是对象的常规属性。它不受范围限制或任何限制。
  6. 接下来,我们只创建另一个对象o2,它也恰好具有bar属性。然后我们致电o.speak,但我们明确覆盖this使用apply所指的内容的选择。我们只是对this关键字引用的对象进行切换。因此,speak函数会警告bar对象的o2属性。
  7. 正如你所看到的那样(希望我知道这首先可能是大脑弯曲),this只不过是一个对象的引用。就这样。它不会在所有范围内限制function的限制范围,this只是一个任意对象。您在this上设置的任何内容不限于范围;相反,它总是可以从您访问该对象的任何地方公开访问。

    令人难以置信的是,一旦你设法绕过它,这一切都是微不足道的。 this指的是一个对象,它只是Javascript的魔术关键字,用于引用一个对象。在任何给定时间,它都会引用某些 对象的简单规则,但所有这些规则都可以弯曲和折断并重新分配。对象只是具有属性的 a 。属性可以是函数。只有函数限制变量范围。这就是它的全部内容。不要试图将其他任何内容解释为此。