Javascript核心知识之this指向

传说中面试热点必考的JavaScript的上下文this指向问题,我决定用心整理下

一、基础知识

1、函数的关键字this表示函数的上下文

2、我要引用一下红宝书第四版里的话,并不是因为我懒,而是它写的太好了。

执行上下文的概念在JavaScript中是颇为重要的。变量或函数的上下文决定了它们可以访问哪些数据,以及它们的行为

全局上下文就是最外层的上下文。根据ECMAScript实现的宿主环境,表示全局上下文的对象可能不一样。在浏览器中,全局上下文就是我们常说的window对象,因此所有通过var定义的全局变量和函数都会成为window对象的属性和方法。

3、MDN

MDN的this

与其他语言相比,函数的 this 关键字在 JavaScript 中的表现略有不同,此外,在严格模式和非严格模式之间也会有一些差别。

在绝大多数情况下,函数的调用方式决定了 this 的值(运行时绑定)。this 不能在执行期间被赋值,并且在每次函数被调用时 this 的值也可能会不同。ES5 引入了 bind 方法来设置函数的 this 值,而不用考虑函数如何被调用的。ES2015 引入了箭头函数,箭头函数不提供自身的 this 绑定(this 的值将保持为闭合词法上下文的值)。

二、规律总结

那JavaScript里面的this到底指向谁呢?

可以粗糙的理解成,this的指向是在调用时确定的。细一点说,又有这么几点规则。

1、在函数体中,非显示或隐式地简单调用函数时,在严格模式下,函数内的this会被绑定到undefined上,在非严格模式下则会被绑定到全局对象window/global上

这是什么意思呢?

        console.log(this);// window对象

        function func1() {
     
            console.log(this);
        }

        func1();// window对象

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

        func2();// undefined

这里要解释一下什么叫做隐式,

比如说,它是通过某个对象进行调用的,就像这样纸

        function fn() {
     
            console.log(this);
        }
        const girl = {
     
            name: 'Yolanda',
            age: 18,
            func: fn
        }

        girl.func();// {name: "Yolanda", age: 18, func: ƒ}

那显式是啥样的,它一般就是通过call、apply、bind指定了明确的上下文,这个一两句说不清楚,后面有空再说叭

2、一般使用new方法调用构造函数时,构造函数内的this会被绑定到新创建的对象上。
         class People {
     
            constructor(name, age){
     
                console.log(this);// People {}
                this.name = name;
                this.age = age;
                console.log(this);//People {name: "Yolanda", age: 18}
            }
            test() {
     
                console.log(this);
            }
        }

        const girl = new People('Yolanda', 18);
        girl.test();// People {name: "Yolanda", age: 18}
3、一般通过call/apply/bind方法显式调用函数时,函数体内的this会被绑定到指定函数的对象上。

这个call/apply/bind的作用就是这个,后面专门写博客说

4、一般通过上下文对象调用函数时,函数体的this会被绑定到该对象上

这个看第二点的栗子

5、在箭头函数中,this的指向是由外层(函数或全局)作用域来决定的。

三、面试题

1、这里有一道面试题,关于箭头函数

const zhangsan = {
     
    name: '张三',
    sayHi() {
     
        console.log(this)
    },
    wait() {
     
        setTimeout(function() {
     
            console.log(this)
        })
    }
}

zhangsan.sayHi()//zhangsan
let func = zhangsan.sayHi
func();//window
zhangsan.wait();//window

改成箭头函数

const lisi = {
     
    name: '李四',
    sayHi() {
     
        console.log(this)
    },
    waitAgain() {
     
        setTimeout(()=> {
     
            console.log(this)
        })
    }
}

lisi.waitAgain();//lisi

2、哦对了,这里还经常会这样出题

就是我前面不是写了对象的调用咩

        function fn() {
     
            console.log(this);
        }
        const girl = {
     
            name: 'Yolanda',
            age: 18,
            func: fn
        }

        girl.func();// {name: "Yolanda", age: 18, func: ƒ}
        const temp = girl.func;
        temp();// window对象

就是说如果是把这个函数保存成一个变量,再调用,那this指针就是window对象了

3、再看一个

var test = {
     
  a: 1,
  b: 2,
  fn: function() {
     
    // 只是定义还没调用的话,这里的this不知道指代的什么,因为函数只有被调用才能确定上下文
    console.log(this.a + this.b);
    console.log(this === test);
  }
}
// 这样显示的就是NAN,因为这样调用的时候,this指代的是window对象
var fn = test.fn;
fn();
// 这样调用显示结果才是3
test.fn();

持续更新中ing…

你可能感兴趣的:(JavaScript,javascript,面试,this)