JavaScript:用堆、运行时、执行上下文图解this的指向问题

89 阅读1分钟

基础知识

JavaScript在宿主环境中即时编译,然后运行。运行时(runtime)在堆(stack)上维护了许多执行上下文(execution contexts),具体来说,代码开始运行时,先创建全局的执行上下文,然后,当遇到函数调用时,堆就会再生成一个执行上下文,如此从下往上不断生成执行上下文,因此,堆的最顶部是正在运行的执行上下文。 而this是函数的一个关键字,是在运行时赋值的,它会随着正在运行的执行上下文的变化而变化。

几种情况的详解

1. 全局对象
function foo () {
    console.log(this === window);
}

foo();   //ture

未命名文件.png

2. 调用函数的对象
function foo () {
    console.log(this === window);
}

let user = {
    count: 10,
    foo: foo,        
    foo1: function() {
    console.log(this === window); 
    }                             
}

let foo1 = user.foo1
foo1()  //true
user.foo1()  //false
user.foo()  //false

未命名文件 (1).png 未命名文件 (3).png 未命名文件 (4).png

3. new关键字
function Person(fn, ln) {
    this.first_name = fn;
    this.last_name = ln;
    this.displayName = function() {
        console.log(`Name: ${this.first_name} ${this.last_name}`)
    }
}

let p = new Person("John", "Reed");
p.displayName();  //Name: John Reed

未命名文件 (5).png 未命名文件 (6).png

4. 箭头函数

箭头函数被调用是不会对this赋值的,由于this是函数的一个关键字,this是在函数内部找不到值的,但由于作用域的缘故,this会向外寻找值。

总结

理解this的关键点在于它是函数的关键字,这一点意味着它在函数作用域的内部,然后它在什么情况下会被赋值。