this的指向问题在前端面试中会经常被问到,所以记录一下,避免以后忘记
注意
- this是在函数执行的时候才能确定指向谁,在函数定义阶段还不能确定
- 以下例子是在非严格模式下执行,严格模式下this默认指向undefined
- es6中this是继承来的,默认指向在定义他时所在的对象
例子1:
function demo() {
var name = 'jeck'
console.log(this.name)
};
demo(); // 打印值为 undefined
demo函数执行的时候是处于window的作用于下面,而window.name = undefined。所以打印值为undefined
例子2:
var person = {
name: 'jeck',
say: function() {
console.log(this.name)
}
};
person.say(); // 打印值为jeck
当执行person的say方法时,由于是由person对象调用的,所以这个时候的this就指向person对象,打印值就为jeck
例子3:
var person = {
name: 'jeck',
b: {
say: function() {
console.log(this.name)
}
}
}
person.b.say(); // 打印值为undefined
由例子3可以看出,调用say方法的对象是person.b,但是该对象里面没有name属性,所以打印值为undefined(不同于原型链,不会一级一级的往上找name属性)
例子4:
var person = {
name: 'jeck',
b: {
name: 'bran',
say: function() {
console.log(this.name)
}
}
}
var o = person.b.say;
o(); // 打印值为undefined
例子4里面给person里面的b对象定义了name属性,但是打印的还是undefined? 因为执行o方法的时候还是在window环境下,相当于执行window.o(); 所以打印值为undefined
例子5:
function Person() {
this.name = 'jeck';
}
var a = new Person();
console.log(a.name) // 打印值为jeck
在根据构造函数创建实例的时候,其实是先创建一个临时对象,然后把构造函数里面的属性赋值给这个临时对象,然后通过(call, apply. bind)等方式改变this的指向(new关键字的实现原理)
例子6:
var person = {
name: '1',
say: () => {
console.log(this.name)
}
}
person.say(); // 打印undefined
由于es6的箭头函数指向定义时的对象,这里的箭头函数,也就是say,所在的作用域其实是最外层的js环境,因为没有其他函数包裹;然后最外层的js环境指向的对象是winodw对象
例子7:
var person = {
name: '1',
say: function() {
const s = () => {
console.log(this.name)
}
return s
}
}
person.say()(); // 打印值为1
由于箭头函数s定义是在person对象的作用域,所以打印值为1