一、this在函数调用时
const fun1 = function () {
console.log(this);
const fun2 = function () {
console.log(this);
};
fun2(); //输出 Window
};
fun1(); //输出 Window
然而严格模式下,结果并不相同;
```'use strict'
const fun1 = function () {
console.log(this);
const fun2 = function () {
console.log(this);
};
fun2(); //输出 undefined
};
fun1(); //输出 undefined
fun1这个函数是全局的,默认挂载在window对象下,this指向它的调用者即window,所以输出window对象,但是在严格模式下,this不允许指向全局变量window,所以输出为undefined。
fun2在函数直接调用时默认指向了全局window,实际上js设计上的缺陷。正确的方式应该是内部函数的this 应该绑定到其外层函数对应的对象上,使用变量替代的方式规避该问题。
二、this作为对象方法
const user = {
userName: '张三',
age: 18,
selfIntroduction: function () {
const str = 'str 我的名字是:' + this.userName + ",年龄是:" + this.age;
console.log(str);//str 我的名字是: 张三,年龄是:18
const loop = function () {
console.log('loop 我的名字是:' + this.userName + ",年龄是:" + this.age);
};
loop(); //loop 我的名字是:undefined,年龄是:undefined
}
};
user.selfIntroduction();
selfIntroduction()方法的调用者是user,所以在该方法内部this指向了他的父对象user,而loop方法输里面指向的window,所以才会输出undefined;所以我尝试修改下,将方法内的this缓存下来,将loop方法的this指向修改
const user = {
userName: '张三',
age: 18,
selfIntroduction: function () {
const str = 'str 我的名字是:' + this.userName + ",年龄是:" + this.age;
console.log(str); //str 我的名字是: 张三,年龄是:18
const that=this;
const loop = function () {
console.log('loop 我的名字是:' + that.userName + ",年龄是:" + that.age);
};
loop(); //loop 我的名字是: 张三,年龄是:18
}
};
user.selfIntroduction();
小结:将selfIntroduction()赋值给了全局变量other,调用other()方法,other挂载在全局函数window对象下,window对象下没有userName 和 age 这两个属性,所以输出为undefined。第二段代码,申明了data对象,包含了username和age属性,一般情况下this指向它的调用者,data是selfIntroduction()的函数的调用者,所以输出了data的userName和age。
三、this作为事件触发
<div id="btn">请点击</div>
<script>
const btn=document.getElementById('btn');
btn.addEventListener('click',function () {
console.log(this);
})
</script>
// 输出 <div id="btn">请点击</div>
小结:这种情况下this指向了事件的事件源event。
四、构造函数
const fun=function(userName){
this.userName=userName;
}
const user=new fun('张三');
console.log(user.userName); //张三
小结:
new关键字构造了一个对象实例,赋值给了user,所以userName就成为了user对象的属性。
五、箭头函数和this
const fun1=()=>{
console.log(this); //输出 Window
};
fun1();
const data={
userName:'张三',
selfIntroduction:function(){
console.log(this); //输出 Object {userName: "张三", selfIntroduction: function}
const fun2=()=>{
console.log(this);
//输出 Object {userName: "张三", selfIntroduction: function}
}
fun2();
}
}
data.selfIntroduction();
在箭头函数中this指向创建者而不是调用者,fun1在全局函数下创建,所以this指向window。
而fun2在对象data下创建,this指向data对象,所以在func2函数内部this指向data对象,
es6的箭头函数的this指向更加完善一些。
六、如何改变this的指向
最常见的用来改变this指向的函数,包括call、apply、bind
const func=function(){
console.log(this);
};
func(); //window
func.apply({userName:"张三"}); //输出 Object {userName: "张三"}
小结:call、apply会将该方法绑定this之后立即执行,而bind方法会返回一个可执行的函数。
七、总结
经过以上的几个案例,可以总结出以下几点:
1. 全局变量默认挂载在window对象下;<br/>
2. 一般情况下this指向它的调用者;<br/>
3. es6的箭头函数中,this指向创建者,并非调用者;<br/>
4. 通过call、apply、bind可以改改变this的指向。
(PS:关于call、apply、bind这三者之间的区别在我的其他博客里有专门的说明。)