面试官:this到底指向谁

98 阅读2分钟

😀 今天来剖析面试中的常考题: JS中的this到底指向谁

📝必须牢记的结论

先熟记以下结论:

  1. 在函数体中,非显式调用一个函数(myFunction())时,会根据严格模式和非严格模式区分this的指向结果。在严格模式下,this指向undefined,非严格模式下,this指向window/global。
  2. 通过new方法调用构造函数创建对象,构造函数的this会指向新创建的对象
  3. 通过call,apply,bind方法显式调用函数时,函数指向指定对象
  4. 通过上下文对象调用函数时,函数指向该上下文对象
  5. 箭头函数中的this指向由外层作用域(函数、全局)决定。
  6. ”谁调用它,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

  1. 箭头函数中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();

  1. 箭头函数的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操作符调用构造函数

  1. 如果构造函数显式返回一个对象(复杂类型),则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)

  1. 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