在 JavaScript 中,this 是一个特殊的关键字,它指向当前函数或方法所属的对象。在不同情况下,this 的指向可能会不同,这取决于函数或方法被调用的方式。
- 在非箭头函数下, this 指向调用其所在函数的对象,而且是离谁近就是指向谁(此对于常规对象,原型链, getter & setter等都适用);
- 构造函数下,this与被创建的新对象绑定;
- DOM事件,this指向触发事件的元素;
- 内联事件分两种情况,bind绑定, call & apply 方法等。
1、在全局环境下,this指向window对象
// 在浏览器中,全局对象为 window 对象:
console.log(this === window); // true
this.a = 30;
console.log(window.a); // 30
2、函数上下文调用
简单来说就是谁调用这个函数,this就指向谁
function foo(num){
console.log("foo: " + num);
//记录foo被调用次数
this.count++;
}
foo.count = 0;
for(let i=0; i<10; i++){
if(i > 5){
foo(i);
}
}
console.log(foo.count); // 0
这里打印是0的原因是因为调用foo方法的是window对象,但是window对象中并没有count这个属性,因此每次执行this.count++的时候都是undefined,最后打印到的foo.count还是0。
3、对象中的this
let o = {
let o = {
prop: "hello",
f: function() {
console.log(this.prop);
}
};
o.f(); // 输出 "hello"
let a = o.f
a()//输出undefined,此时相当于window.a(),this指向window对象
4、构造函数中的this
构造函数中的this与被创建的新对象绑定。
function fruit(name){
console.log(name, this);
}
const f1 = new fruit('apple'); // apple fruit {}
const f2 = new fruit('banana'); // banana fruit {}
console.log(f1, f2, f1 === f2); // fruit {} fruit {} false
从上面例子可以看出来f1和f2的this是不一样的
5、显式绑定(call和apply绑定this时会调用一次函数,bind则不会调用)
1、call、apply
apply 方法接受一个数组或类数组作为函数的参数,而 call 则接受多个参数列表。
// 水果对象
function fruit(){
console.log(this.name, arguments);
}
var apple = {
name: '苹果'
}
var banana = {
name: '香蕉'
}
fruit.call(banana, banana, apple) // 香蕉 { '0': { name: '香蕉' }, '1': { name: '苹果' } }
fruit.apply(apple, [banana, apple]) 苹果 { '0': { name: '香蕉' }, '1': { name: '苹果' } }
2、bind
下面是bind绑定的示例,只是将一个值绑定到函数的this上,并将绑定好的函数返回,只有在fruit函数才会输出信息,例:
function fruit(){
console.log(this.name);
}
let apple = {
name: '苹果'
}
fruit = fruit.bind(apple);
fruit(); // 苹果
6、this的优先级问题
- new绑定
- 显式绑定
- 隐式绑定
- 默认绑定(严格模式下会绑定到undefined)
7、箭头函数的this
由于箭头函数不绑定this, 它会捕获其所在(即定义的位置)上下文的this值, 作为自己的this值,所以 call() / apply() / bind() 方法对于箭头函数来说只是传入参数,对它的 this 毫无影响。
function Person() {
this.age = 0;
setInterval(() => {
// 回调里面的 `this` 变量就指向了期望的那个对象了
console.log(this)
}, 3000);
}
var p = new Person();