Skip to main content

深入理解 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

显示绑定(例如 callapplybind)时,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.sayHellothis 指代 B

  • 注意:箭头函数的 this 指向不能改变,不会随着 callapplybind 的调用而变化。

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 指向返回的这个对象。

  • 通过 callapplybind 绑定的函数,this 指代第一个绑定的函数参数。

  • 箭头函数的 this 指向包裹这个箭头函数的上下文的 this

  • 定时器函数的 this 指代 window

  • 立即执行函数的 this 指代 window

  • 绑定事件函数的 this 指向函数的调用者。