美文网首页
你不知道的JavaScript(一)|this和对象原型

你不知道的JavaScript(一)|this和对象原型

作者: xpwei | 来源:发表于2017-09-27 16:08 被阅读17次

    this误解
    指向自身
    以下代码看到this并不像我们所想的那样指向函数本身:

    function foo(num) {
        console.log("foo: " + num);
        // 记录foo 被调用的次数
        this.count++;
    }
    foo.count = 0;
    var i;
    for (i = 0; i < 10; i++) {
        if (i > 5) {
            foo(i);
        }
    }
    // foo: 6
    // foo: 7
    // foo: 8
    // foo: 9
    // foo 被调用了多少次?
    console.log(foo.count); // 0 -- WTF?
    

    console.log语句产生了4条输出,证明foo(..)确实被调用了4次,但是foo.count仍然是0。这段代码在无意中创建了一个全局变量count,它的值是NaN。
    代码应改为如下:

    function foo(num) {
        console.log("foo: " + num);
        // 记录foo 被调用的次数
        // 注意,在当前的调用方式下(参见下方代码),this 确实指向foo
        this.count++;
    }
    foo.count = 0;
    var i;
    for (i = 0; i < 10; i++) {
        if (i > 5) {
            // 使用call(..) 可以确保this 指向函数对象foo 本身
            foo.call(foo, i);
        }
    }
    // foo: 6
    // foo: 7
    // foo: 8
    // foo: 9
    // foo 被调用了多少次?
    console.log(foo.count); // 4
    

    它的作用域
    需要明确的是,this在任何情况下都不指向函数的词法作用域。在JavaScript内部,作用域确实和对象类似,可见的标识符都是它的属性。但是作用域“对象”无法通过JavaScript代码访问,它存在于JavaScript引擎内部。

    function foo() {
        var a = 2;
        this.bar();
    }
    function bar() {
        console.log(this.a);
    }
    foo(); // ReferenceError: a is not defined
    

    这段代码中的错误不止一个。首先,这段代码试图通过this.bar()来引用bar()函数,这是绝对不可能成功的。调用bar()最自然的方法是省略前面的this,直接使用词法引用标识符。此外,编写这段代码的开发者还试图使用this联通foo()和bar()的词法作用域,从而让bar()可以访问foo()作用域里的变量a。这个是不可能实现的,不能使用this来引用一个词法作用域内部的东西。

    this到底是什么
    this是在运行时进行绑定的,并不是在编写时绑定,它的上下文取决于函数调用时的各种条件。this的绑定和函数声明的位置没有任何关系,只取决于函数的调用方式。
    当一个函数被调用时,会创建一个活动记录(有时候也称为执行上下文)。这个记录会包含函数在哪里被调用(调用栈)、函数的调用方法、传入的参数等信息。this就是记录的其中一个属性,会在函数执行的过程中用到。

    母亲,人间第一亲;母爱,人间第一情

    相关文章

      网友评论

          本文标题:你不知道的JavaScript(一)|this和对象原型

          本文链接:https://www.haomeiwen.com/subject/sqduextx.html