深入理解 JS 的 this
一、什么是 this
this
是 JS 的一个关键字。
它是函数运行时,在函数体内部自动生成的一个对象,只能在函数体内部使用。
function fn() {
this.age = 23;
}
上面代码中,函数 fn 运行时,内部会自动有一个 this
对象可以使用。
函数的不同使用场合,this
指代不同的值。
总的来说,this
就是函数运行时所在的环境对象。
二、this 的判断
1、普通函数的 this
普通函数的 this
指代 window
,严格模式下会抛出错误 undefined
('use strict')
var age = 23;
function fn() {
console.log(this, this.age);
}
fn(); // window 23
上面代码中,fn() 的 this
指代 window
。
2、对象函数的 this
函数作为对象属性执行时,this
指代上级对象。
function fn() {
console.log(this, this.age);
}
var obj = {
sayHi: function () {
console.log(this);
}
}
obj.sayHi();//{sayHi: ƒ}
上面代码中,sayHi() 函数作为 obj 对象的属性执行,其中的 this
指代上级对象 obj。
3、构造函数的 this
如果构造函数的实例没有 return
,则 this
指向这个实例:
function Star(name, age) {
this.name = name;
this.age = age;
}
let mid = new Star('Tim', 23);
console.log(mid); // Star { name: "Tim", age: 23 }
如果构造函数的实例存在 return
返回一个对象,则 this
指向返回的这个对象:
function Star(name, age) {
this.name = name;
this.age = age;
let obj = {
age: 18
}
return obj;
}
let sup = new Star('Tim', 23);
console.log(sup); // { age: 18 }
4、通过 call、apply、bind 绑定的 this
显示绑定(例如 call
、apply
、bind
)时,this
指代第一个绑定的函数参数。
let obj = {}
let fn = function () {
console.log(this)
}
fn.bind().bind(obj)()
上面的代码中,不管给函数 bind
几次,fn
中的 this
永远由第一次 bind
决定,所以结果永远是 window
。
5、箭头函数的 this
箭头函数 this
指向的是函数定义位置的上下文 this
(即包裹这个箭头函数的上下文的 this
)
var name = 'window'; // 其实是 window.name = 'window'
var A = {
name: 'A',
sayHello: function () {
console.log(this.name)
}
}
A.sayHello(); // 输出 A
var B = {
name: 'B',
sayHello: () => {
console.log(this.name)
}
}
B.sayHello(); // window
这里的箭头函数 sayHello 所在的作用域其实是最外层的 js 环境(因为没有其他函数包裹),最外层的 js 环境指向的对象是 winodw
对象,所以这里的 this
指向的是 window
对象。
那上面箭头函数的 this
如何改造成绑定 B 呢?
var name = 'window';
var B = {
name: 'B',
sayHello: function () {
var s = () => console.log(this.name)
return s // 返回箭头函数 s
}
}
var sayHello = B.sayHello();
sayHello(); // 输出 B
上面箭头函数 s 所在的作用域是 sayHello,因此 B.sayHello 的 this
指代 B。
- 注意:箭头函数的 this 指向不能改变,不会随着
call
、apply
、bind
的调用而变化。
6、定时器函数的 this
定时器函数的 this
指代 window
。
setTimeout(function () {
console.log(this);
}, 2000); // this 指向 window
7、立即执行函数的 this
立即执行函数的 this
指代 window
。
(function () {
console.log(this); // this 指向 window
})();
8、绑定事件函数的 this
绑定事件函数的 this
指向函数的调用者(即接收事件的 HTML 元素)
var btn = document.querySelector('button');
btn.onclick = function () {
console.log(this); // btn <button>点击</button>
}
三、总结
普通函数的
this
指代window
。函数作为对象属性执行时,
this
指代上级对象。构造函数的实例没有
return
时,则this
指向这个实例,存在return
返回一个对象时,则this
指向返回的这个对象。通过
call
、apply
、bind
绑定的函数,this
指代第一个绑定的函数参数。箭头函数的
this
指向包裹这个箭头函数的上下文的this
。定时器函数的
this
指代window
。立即执行函数的
this
指代window
。绑定事件函数的
this
指向函数的调用者。