理解 This 关键字

理解 This 关键字

JavaScript 中的 this 所指向的对象,取决于上下文以及函数被调用的方式,本文列举了几种常见的情况,帮助大家理解。

一、全局上下文

当直接在一个全局的上下文中,使用 this 指针的时候,this 指针会指向到全局对象上。例如在浏览器的调试工具栏中直接打印 this 指针,其指向的是 Window 对象:

调试工具栏中的 this 指针

node 中打印 this 指针,其指向的是 node 提供的全局对象,其中包含了进程信息等:

Node 中的 this 指针

二、Function 上下文

在 Function 上下文中,this 的值取决于 function 是如何被调用的。

(1) Function 调用

this 指针定义在一个 function 中,那么此 this 仍然会指向全局对象:

function foo() { 
    console.log(this) 
}

foo(); // Window {parent: Window, postMessage: ƒ, blur: ƒ, focus: ƒ, close: ƒ, …}

(2) 严格模式下的 Function 调用

如果在严格模式下定义的 function 的话,this 指针的值将会是 undefined

function foo() { 
    'use strict';
    console.log(this) 
}

foo(); // undefined

(3) Method 调用

Method 调用指的是,function 作为一个对象的属性而存在。当 this 指针被定义在一个对象内的时候,那么其将会指向紧紧包裹自己的这个对象。

var obj = {
    name: 'outerObj',
    innerObj: {
        name: 'innerObj',
        foo: function() {
            console.log(this.name)
        }
    }
};

console.log(obj.innerObj.foo()) // innerObj

(4) 构造器调用

function 被用于构造器的时候,那么定义在构造器内部的 this 指针将会指向此构造器新 new 出来的实例对象

function Person(name) {
    this.name = name
    console.log(this)
}

console.log(new Person("Tom")) // Person {name: "Tom"}

(5) call()apply()bind() 调用

这三个函数最大的特点就是,你可以通过参数为他们指定 this 指针所需要指向的对象:

function add(inc1, inc2) {
    var value = this.a + inc1 + inc2;
    console.log(this)
    return value;
}

var o = { 
    a : 4 
};

console.log(add.call(o, 5, 6)) // {a: 4}
console.log(add.apply(o, [5, 6])) // {a: 4}

var g = add.bind(o, 5, 6)
console.log(g()) // {a: 4}

(6) ES6 箭头函数调用

当你使用 ES6 箭头函数的时候,this 指针返回的总是箭头函数定义所在位置的上一级的函数作用域this 对象,是箭头函数被 function() { } 包裹的作用域中的 this 对象。如下面示例,this 指向的是 log() 函数内部的 this 指针的值:

class Student {

    log() {
        // 这个地方的 this 的值
        setTimeout(() => console.log(this === student), 100)
    }

}

const student = new Student()
student.log() // true

This 在箭头函数中

但是如果上一级并不是位于函数作用域中,而是位于 Object 对象嵌套层级中,则需要继续向上找函数作用域,因为 Object 嵌套层级不构成单独的作用域。如下所示 this 指针指向的是 Window 对象,而非 o 对象:

var o = {
    b: () => {
        console.log('this is', this); // this is Window
    }
}

o.b();

三、参考

扫描下面二维码,在手机端阅读: