前言
正值春招火热招聘阶段,我近期在复习JavaScript的相关知识点,其中“this”知识点是前端面试中高频面试内容,因此整理和总结一篇相关知识点文章和大家分享!
在 JavaScript 中,
this
是一个非常重要的关键字,它在函数和对象操作中扮演着关键角色。然而,this
的指向规则并不总是直观的,这让很多初学者感到困惑。本文将通过通俗易懂的方式,结合实际代码示例,帮助你彻底理解this
的指向规则。
一、this
的指向规则
this
的指向取决于函数的调用方式,而不是函数的定义方式。虽然“谁调用它,this
就指向谁”这种说法有一定道理,但并不完全准确。以下是 this
指向的几种常见情况:
1. 全局环境中的this
在全局环境下调用函数时,this
的指向会根据是否开启严格模式而有所不同。
非严格模式:
this
指向全局对象(浏览器中是window
,Node.js 中是global
)。严格模式:
this
指向undefined
。
function f1() {console.log(this);
}
function f2() {'use strict';console.log(this);
}
f1(); // 非严格模式:window 或 global
f2(); // 严格模式:undefined
2. 使用 new
调用构造函数
当使用 new
关键字调用函数时,this
会被绑定到新创建的对象上。
function Person(name) {this.name = name;
}
const person = new Person('Alice');
console.log(person.name); // 输出:Alice
console.log(person); // 输出:{ name: 'Alice' }
在这个例子中,
this
指向了通过new
创建的person
对象。
3. 使用 call、apply、bind 显式绑定 this
call
、apply
和 bind
是 JavaScript 中用来显式改变函数内部 this 指向的方法。
call
和apply
:立即执行函数,并将this
绑定到指定对象。call
和apply
的区别在于参数的传递方式:call
接收多个参数,apply
接收一个数组作为参数。
const obj = { name: 'Bob' };
function greet() {console.log(`Hello, ${this.name}!`);
}
greet.call(obj); // 输出:Hello, Bob!
greet.apply(obj); // 输出:Hello, Bob!
bind
:返回一个新函数,该函数的 this 指向被永久绑定到指定对象。
const greetBob = greet.bind(obj);
greetBob(); // 输出:Hello, Bob!
4. 通过上下文对象调用函数
当通过对象的方法调用函数时,this 指向该对象。
const student = {name: 'Alice',greet: function() {console.log(`Hello, ${this.name}!`);}
};
student.greet(); // 输出:Hello, Alice!
如果函数被赋值给其他变量后调用,this 的指向会丢失,恢复到全局对象。
const greet = student.greet;
greet(); // 输出:Hello, undefined!
5. 箭头函数中的this
箭头函数是 ES6 引入的一种简化语法,它的 this 指向在定义时就已经确定,始终指向外层作用域的 this。
const obj = {name: 'Alice',greet: () => {console.log(`Hello, ${this.name}!`);}
};
obj.greet(); // 输出:Hello, undefined!
在这个例子中,箭头函数的 this 指向全局对象,而不是obj。
二、更复杂的场景
1、事件处理中的 this
在 DOM 事件处理中,事件处理函数的 this 指向绑定事件的元素。
document.getElementById('button').addEventListener('click', function() {console.log(this); // 指向绑定事件的按钮元素
});
如果事件处理函数是一个箭头函数, this 的指向会继承自外层作用域。
const button = document.getElementById('button');
button.addEventListener('click', () => {console.log(this); // 指向全局对象(浏览器中是 window)
});
2、嵌套函数中的 this
在嵌套函数中,this 的指向可能会变得复杂。普通函数的 this 指向取决于调用方式,而箭头函数的this 指向则继承自外层作用域。
const obj = {name: 'Alice',greet: function() {const inner = () => {console.log(`Hello, ${this.name}!`);};inner();}
};
obj.greet(); // 输出:Hello, Alice!
在这个例子中,箭头函数
inner
的 this 继承自外层的greet
函数的 this,指向obj
。
三、总结
this
的指向规则虽然复杂,但只要掌握以下要点,就可以轻松应对:
全局环境:非严格模式下指向全局对象,严格模式下指向
undefined
。构造函数:使用
new
时,this
指向新创建的对象。显式绑定:通过
call
、apply
、bind
可以显式改变this
的指向。上下文对象:通过对象调用函数时,
this
指向该对象。箭头函数:
this
指向外层作用域。