JavaScript this 关键字

111 阅读2分钟

1. 什么是this

在JavaScript中,this是一个特殊的关键字,它代表当前执行上下文中的对象。这里的“当前执行上下文”可以是一个函数、一个对象或者全局作用域。

2. this的四种常见情况

  1. 全局上下文
    在全局作用域或者函数外部,this指向全局对象。在浏览器中,这个全局对象就是window
console.log(this.document === document); // true
console.log(this === window); // true
this.a = 37;
console.log(window.a); // 37
  1. 函数上下文
    在函数内部,this的值取决于函数是如何被调用的。

    • 简单调用
      如果一个函数不是作为对象的方法被调用,那么this通常指向全局对象。
    function f1(){
    	return this;
    }
    f1() === window; // 在浏览器中,非严格模式下为true
    
    • 作为对象的方法调用
      当函数作为对象的方法被调用时,this指向该对象。
    var o = {
    	prop: 37,
    	f: function() {
    		return this.prop;
    	}
    };
    console.log(o.f()); // 37
    
  2. 构造函数
    当一个函数通过new关键字被用作构造函数时,this指向新创建的对象实例。

function C(){
	this.a = 37;
}
var o = new C();
console.log(o.a); // 37
  1. 使用.call().apply().bind()
    这三个方法可以显式地指定函数执行时的this值。
function f(){
	return this.a;
}
var o = {a: 37};
console.log(f.call(o)); // 37
console.log(f.apply(o)); // 37
console.log(f.bind(o)()); // 37
  1. 箭头函数中的this
    箭头函数是ES6引入的一个新特性,它在处理this时与普通函数有所不同。箭头函数没有自己的this绑定,它会捕获其所在上下文的this值。
    // this绑定的是全局变量
    let base_num = 100;
    function opreate(a, b) {
    let add = () => {
         return this.base_num + a + b;
        }
        return add();
    }
    console.log(opreate(1, 2)) ;
    
    // this绑定的是info
    let info = {
    a: 1,
    f: function() {
        let innerFunc = () =>{
            console.log(this.a);
        }
        innerFunc(); 
        }
    }
    info.f();
  1. 类中的this
    ES6引入了类的概念,类中的this与构造函数中的this类似,指向类的实例。
class MyClass {
	constructor() {
		this.a = 1;
	}
	method() {
		return this.a;
	}
}

const instance = new MyClass();
console.log(instance.method()); // 1
  1. 回调函数中的 this
    在回调函数中,this的值可能会发生变化,因为它取决于回调函数的调用方式。但是可以通过显示的bind或者隐式的绑定this对象。
var obj = {
	a: 1,
	b: function() {
		setTimeout(function() {  // 这边因为setTimeout是全局函数调用,没有绑定对象,所以这边的this就指向了全局变量
			console.log(this.a); // undefined
		}, 100);
	}
};
obj.b();

// 隐式绑定,通过箭头函数捕获其所在上下文的`this`值来隐式绑定
var obj = {
    a: 1,
    b: function () {
        setTimeout(() => {
            // 这边因为setTimeout是全局函数调用,没有绑定对象,所以这边的this就指向了全局变量
            console.log(this.a); // 1
        }, 100);
    },
};
obj.b();

// 显示绑定
var obj = {
    a: 1,
    b: function () {
        setTimeout(
            function () {
                // 这边因为setTimeout是全局函数调用,没有绑定对象,所以这边的this就指向了全局变量
                console.log(this.a); // 1
            }.bind(obj),
            100
        );
    },
};
obj.b();