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

标签 javascript

我试图理解“这个”,并且我所看过的所有内容都在谈论上下文。这导致我想到“ this”是范围限制器的想法。它可以确保使用适当的范围来引用变量,主要是通过使变量在范围内保持“局部” -ish,并防止它们与运行代码所在的位置相距太远。

我的问题是:正确吗?我尝试使用试图传达的概念进行搜索,但是结果却完全不对。 “ this”有很多细微差别,从我读过的书中,我觉得这比我看过的要好,但我想确保自己的想法是正确的。

最佳答案

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

另一方面,this只是对“当前”对象的“魔术”引用。也许首先在其他古典语言的背景下解释这个想法可能会有所帮助:

class Foo {

    protected $bar;

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

}


在PHP中,魔术关键字$this指向当前对象实例。每次调用new Foo时,都会创建此类的新实例。每次调用$foo->baz()时,都会执行相同的功能,尽管将$this设置为适当的对象实例,这样每个对象实例都可以访问自己的数据。

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

class Foo:

    def baz(self):
        print self.bar


Python没有魔术关键字来引用当前对象实例。取而代之的是,对对象的每个方法调用都将当前对象显式传递为其第一个参数。通常将其命名为self。如果Python对您来说似乎太陌生,则PHP语法中的上述内容应为:

class Foo {

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

}


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

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


这基本上与上面的类方法完全相同,不同之处在于显式注入了$obj而不是神奇地“存在”了$this

除了具有this在每个函数中可用(不仅是“类”函数)而且对象this指向的对象可以在运行时自由更改之外,Javascript也具有相同的功能。 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并不限制任何范围。这里发生了什么事?


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);

Foo构造函数分配该新对象的bar属性。

tmp.bar = 'baz';

新对象已分配给o

var o = tmp;

o.speak()是通过其prototype绑定到该对象的函数。 o.speak()内部的this称为speak(),是指o对象。由于该对象具有属性bar,因此可以使用。
注意,也可以执行alert(o.bar).bar属性最初是在this上设置的,然后this变为o。因此,o具有属性.bar,这是对象的常规属性。它不受范围限制或其他任何限制。
接下来,我们仅创建另一个对象o2,该对象也恰好具有bar属性。然后我们调用o.speak,但是我们显式地覆盖了this使用apply所指的选择。我们只需对this关键字所指的对象进行切换。因此,speak函数会提醒bar对象的o2属性。


如您所见(希望,起初我知道这可能是大脑弯曲),this仅是对对象的引用而已。就这样。它并不限制任何事物的范围。 function的限制范围,this只是一个任意对象。您在this上设置的任何内容均不受范围限制;相反,它始终可以从您有权访问该对象的任何地方公开访问。

一旦您设法将头围起来,这一切简直令人难以置信。 this引用对象,它只是Javascript引用对象的magic关键字。在任何给定时间,它所引用的对象都有某些琐碎的规则,但是所有这些规则都可以弯曲,折断和重新分配。对象只是具有属性的事物。这些属性可以是函数。仅函数限制变量范围。这几乎就是它的全部。请勿尝试对此进行任何其他解释。

关于javascript - “这个”作为范围限制器?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24783466/

相关文章:

Javascript 变量不会更新番茄时钟

javascript - Meteor js - "please re-enter your password to do that"- 如何在已经登录的情况下重新授权?

javascript - 请修复代码 append() 和 empty()

javascript - 在javascript中将日期转换为其他格式

javascript - Google map - 更改图 block 叠加层的 Pane 顺序?

javascript - 更改我的函数异步 : false to async: true with JQuery and Ajax

javascript - 将 Ember.js 与外部代码(例如,Android 的 WebView)集成的最佳方式

javascript - Sencha 触摸 : update view during function

javascript - 无法更改完整日历 v4 中事件点击的 View ?

JavaScript 使用逗号进行短路变量赋值