知识前提:
1.Function 是 js中的一个内置对象,所有的代码执行时都是在对应的上下文中执行的。
2.执行上下文的创建阶段有一个重要的点那就是改变this指针的情况。
参考:js[执行上下文、执行栈]、js[内置对象]
记住5点概要
1.在普通函数中,this默认指向window对象
function a(){
console.log('全局上下文中a的this',this);
function b(){
console.log('函数上下文中b的this',this);
}
b();
}
a();
运行结果:
在普通函数中,无论是在全局上下文还是函数上下文中,this都是默认指向window对象的。默认情况下,上下文创建过程中this的初始指向就是window
2.在构造函数中,this指向new出来的实例对象(构造函数和普通函数的区别可以理解为是否通过new关键字来构建实例对象)
function a(){
console.log('当作构造函数使用的a中的this',this);
}
let a1 = new a();
let a2 = new a();
console.log('实例a1对象',a1)
console.log('实例a2对象',a2)
运行结果:
先了解new函数实例化对象的过程:
参考:https://www.cnblogs.com/ysk123/p/10224391.html
总共干了三件事:
- 创建一个空对象,并使该空对象继承构造函数的原型prototype;
- 执行构造函数,并将this指向刚刚创建的新对象;
- 返回新对象;
因此就有使用new构建几个对象就会对该函数执行几次,并且创建几次空对象,然后将this的指向进行改变为新对象,从而出现上面的打印结果
3.在对象的直属方法中,this 指向该对象
let a = {
a:'123',
sleep(){
console.log('对象方法:sleep')
},
run(){
console.log('对象属性',this.a);
this.sleep();
}
}
a.run();
运行结果
在对象方法中this是指向其对象的,因此可以拿到这个对象的方法和属性,
注意1:对象的属性中的this是无法拿到这个对象的内容的,因为this的指向任然为window。
window.d = 'window的d'
let a = {
a:'123',
test: this.d,
run(){
console.log('对象属性a',this.a);
console.log('对象属性test',this.test);
}
}
a.run();
运行结果
可以看出属性中的this的指向任然指向的是最外层对象window而不是该对象。原因与对象的创建过程有关。
注意2:对象的非直属方法任然指向window
let a = {
a:'123',
run(){
console.log('对象属性a',this.a);
// run方法中定义了方法
function t(){
console.log(this);
}
t()
}
}
a.run();
运行结果
4.apply 和 call 和 bind 函数可以改变this的指向,其第一个参数传递什么,this就指向什么。
参考:https://blog.csdn.net/lxy869718069/article/details/104691210
5.事件绑定中,事件触发的函数中this指向当前绑定的事件
有三种方法可以改变 return 函数内部this的指向问题
1.bind()/call()/apply 方法
2.使用变量(如:that)保存上层的this
3.使用箭头函数
总结:
1.在全局执行环境中(在任何函数体外部),this都是指向全局对象。
2.在函数内容,this指向取决于函数调用的方式:
普通函数、构造函数、对象方法、以及主动调用call()/apply()/bind()方法的情况