深入理解闭包(三)——确定this指向

原文地址:深入理解闭包(三)——确定this指向

我们在前面说过,在执行上下文创建过程中做了三件事:创建变量对象,生成作用域链,确定this指向。今天我们就来探讨一下this指向的问题。首先先回顾一下我们执行上下文的生命周期图:

深入理解闭包(三)——确定this指向_第1张图片

执行上下文是函数被调用时创建的,创建过程包括确定this指向,所以 this的指向是在函数被调用时确定的

我们知道,this对象是在运行时基于函数的执行环境绑定的:在全局环境中,this指向window,当函数被作为某个对象的方法调用时,this指向那个对象。不过实际情况中往往没有那么好判断,今天我们就来梳理一下。

全局对象中的this

在全局环境下,this永远指向window。

    console.log(this);    //window

函数中的this

this指向调用这个函数的对象。

    var a = 10;
    function test() {
        var a = 20;
        console.log(this.a);
    }
    test();   //10

由于函数test是被全局对象(window)调用的,因此函数内部的this指向window。

    var a = 20;
    var obj = {
        a: 10,
        b:this.a,
        fn: function () {
            return this.a;
        }
    }

    console.log(obj.fn());   //10
    console.log(obj.b);      //20

由于函数fn是被对象obj调用的,因此函数fn内部的this指向对象obj。
另外,由于obj不是个函数,不适合上面的规则,我们要单独讨论,如果obj对象在全局创建,那么obj里面的this指向window。

构造函数

构造函数和其他函数的唯一区别,就是他们的调用方式不同。任何函数,只要通过new操作符来调用,那它就可以作为构造函数,调用时经历以下四个步骤:

  1. 创建一个新对象;
  2. 将构造函数的作用域赋给新对象(因此this就指向了这个新对象);
  3. 执行构造函数中的代码(为这个新对象添加属性);
  4. 返回新对象。
    function Test() {
        this.a = 1;
        console.log(this.a);      //1
    }
    var fun = new Test();
    console.log(fun.a);          //1

创建新对象new Test()后,this指向这个新对象,然后为这个新对象添加属性a = 1,再执行console.log(this.a),此时输出的就是刚添加的a值。返回这个新对象传递给了实例对象fun,此时this指向了实例fun,因此fun.a也为1。

函数用call或apply调用

我们可以利用call或apply手动设置this的指向,这两个方法的第一个参数都是this将要指向的对象,后面的参数,都是向将要执行的函数传递参数。其中call以一个一个的形式传递,apply以数组的形式传递,这是他们唯一的不同。

    var obj = {
        num: 10
    }
    function test(a, b) {
        console.log(this.num + a + b);
    }
    test(20,30);                    //NaN
    test.call(obj, 20, 30);        // 60
    test.apply(obj, [20, 30]);     // 60

这个例子很容易理解,本来调用test函数this指向全局对象,是无法访问到obj对象中的num的,但是利用call和apply方法将this指向了obj对象,所以可以顺利输出。

以上就是我目前知道的关于this指向的几种情况,以后可能会再补充。

你可能感兴趣的:(深入理解闭包(三)——确定this指向)