😀 今天来剖析面试中的常考题: JS中的this到底指向谁
📝必须牢记的结论
先熟记以下结论:
- 在函数体中,非显式调用一个函数(myFunction())时,会根据严格模式和非严格模式区分this的指向结果。在严格模式下,this指向undefined,非严格模式下,this指向window/global。
- 通过new方法调用构造函数创建对象,构造函数的this会指向新创建的对象
- 通过call,apply,bind方法显式调用函数时,函数指向指定对象
- 通过上下文对象调用函数时,函数指向该上下文对象
- 箭头函数中的this指向由外层作用域(函数、全局)决定。
- ”谁调用它,this就指向谁“,一般面试中能用上的经验总结,但不够准确
📃面试常考题分析
1.无显示绑定时,this指向上一级调用它的对象或window
若直接调用fn1,得到的输出是undefined, 若调用对象属性上的fn方法,得到的输出是Richard.
var foo = {
name: "Richard",
fn: function() {
console.log(this.name);
}
}
var fn1 = foo.fn;
fn1(); // undefined
foo.fn(); // Richard
o2.fn的最终调用是o1,所以答案是o1;
o3.fn()通过var fn=o1.fn的赋值进行”裸奔”调用,所以this指向window,答案是undefined
const o1 = {
text: 'o1',
fn: function() {
return this.text;
}
}
const o2 = {
text: 'o2',
fn: function() {
return o1.fn();
}
}
const o3 = {
text: 'o3',
fn: function() {
var fn = o1.fn;
return fn();
}
}
o1.fn(); // o1
o2.fn(); // o1
o3.fn(); // undefined
2. 箭头函数中的this
- 箭头函数中this的值是在函数定义时的外层作用域中的this值。
this指向window, 执行foo.fn()等价于执行setTimeout中的匿名函数,
const foo = {
fn: function() {
setTimeout(function(){
console.log(this);
})
}
}
foo.fn();
this指向foo, 箭头函数中的this继承外层作用域的this值,执行foo.fn()等价于执行setTimeout中的箭头函数,它的外层作用域的this值即fn的this指向
const foo = {
fn: function() {
setTimeout(() => {
console.log(this);
})
}
}
foo.fn();
- 箭头函数的this指向无法修改
function foo(){
return a => {
console.log(this.a);
}
}
const obj1 = {
a: 2
}
const obj2 = {
a: 3
}
const bar = foo.call(obj1);
console.log(bar.call(obj2));// 2
3. new操作符调用构造函数
- 如果构造函数显式返回一个对象(复杂类型),则this指向这个返回的对象,如果返回的不是对象(基本类型),则this仍指向实例
执行以下代码将输出undefined, 此时instance的this指向Foo返回的空对象o
//场景 1
function Foo() {
this.user= "Lucas"
const o = {)
return o
}
const instance = new Foo()
console.log(instance.user)
执行以下代码将输出Lucas 此时instance返回的是目标对象实例的this。
// 场景 2
function Foo() {
this.user= "Lucas"
return 1;
}
const instance= new Foo() console.log(instance.user)
- new操作符的优先级比显式bind绑定更高
function foo () {
this.a = a
}
const obj1 = {}
var bar = foo.bind(obj1)
bar(2)
console.log(obj1.a); // 2
var baz = new bar(3);
console.log(baz.a); // 3