this 的指向有哪些?
面试高频指数:★★★★★
函数的调用方式决定了 this 的值(运行时绑定)。this 不能在执行期间被赋值,并且在每次函数被调用时 this 的值也可能会不同。
this 的指向有以下七种:
全局上下文
this 指向全局对象
console.log(this === window); // true
a = 37;
console.log(window\.a); // 37
函数上下文
this 指向取决于函数被调用的方式:
- 作为对象的方法调用,this 指向该对象
- 作为普通函数调用
- 严格模式下,指向全局对象,浏览器中就是 window
- 非严格模式下,为 undefined
- call、apply、bind 调用,this 指向绑定的对象
- 作为构造函数调用,如使用 new,this 指向新的对象
function f1(){
return this;
}
//在浏览器中:this 指向全局对象 window
f1() === window;
//在 Node 中:this 指向 global
f1() === global;
// 严格模式下:this 指向 undefined
function f2(){
"use strict";
return this;
}
f2() === undefined; // true
// call 方法:this 指向传入的指定对象 o
function add(c, d) {
return this.a + this.b + c + d;
}
var o = {a: 1, b: 3};
add.call(o, 5, 7); // 16
类上下文
this 指向类。在类的构造函数中,this 是一个常规对象。类中所有非静态的方法都会被添加到 this 的原型中:
class Car {
constructor() {
// 使用 bind() 方法改变 this 指向
this.sayBye = this.sayBye.bind(this);
}
sayHi() {
console.log(`Hello from ${this.name}`);
}
sayBye() {
console.log(`Bye from ${this.name}`);
}
get name() {
return 'Ferrari';
}
}
class Bird {
get name() {
return 'Tweety';
}
}
const car = new Car();
const bird = new Bird();
// this 指向调用者
car.sayHi(); // Hello from Ferrari
bird.sayHi = car.sayHi;
bird.sayHi(); // Hello from Tweety
// bind() 方法改变了 this 指向,this 指向类 Car
bird.sayBye = car.sayBye;
bird.sayBye(); // Bye from Ferrari
箭头函数
this与封闭词法环境的 this 保持一致。在全局代码中,它将被设置为全局对象。
var window = this;
var foo = (() => this);
console.log(foo() === window); // true
原型链中的 this
如果该方法存在于一个对象的原型链上,那么 this 指向的是调用这个方法的对象。
var o = {
f: function() {
return this.a + this.b;
}
};
var p = Object.create(o);
p.a = 1;
p.b = 4;
console.log(p.f()); // 5
作为一个 DOM 事件处理函数
当函数被用作事件处理函数时,它的 this 指向触发事件的元素。
function bluify(e) {
console.log(this === e.currentTarget); // true
this.style.backgroundColor = 'blue'
}
// 获取 id 为 test 的 button
let testBtn = document.getElementsById('test');
// 将 bluify 作为元素的点击监听函数,当元素被点击时,就会变成蓝色
testBtn.addEventListener('click', bluify, false);
getter 与 setter 中的 this
用作 getter 或 setter 的函数都会把 this 绑定到设置或获取属性的对象。
var o = {
a: 1,
b: 2,
get sum() {
return (this.a + this.b);
}
};
console.log(o.sum); // 输出 3
小练习
给出下面代码的输出结果:
var length = 10;
function fn() {
return this.length + 1;
}
var obj = {
length: 5,
test1: function() {
return fn();
}
};
obj.test2 = fn;
console.log(obj.test1.call()); // (1)
console.log(obj.test1()); // (2)
console.log(obj.test2.call()); // (3)
console.log(obj.test2()); // (4)
答案:输出如下:
1 处为:11, this 指向 window, 因为 call 方法没有执行具体要绑定的对象。 2 处为:11,this 指向 window,返回的 fn 函数的 this 指向 window 3 处为:11,原因同 1 处 4 处为: 6,this 指向 obj,此处函数作为对象 obj 的方法调用