7个关于JS中的this关键字面试题
在JS中,this 指的是函数调用的上下文。
但其实,它的行为很复杂,这也是在面试中,常常会被问到的问题。
下面来说说7个有趣的面试题。
一、可变和属性
先来看一段代码:
const object = { message: 'Hello, World!', getMessage() { const message = 'Hello, Earth!'; return this.message; } }; console.log(object.getMessage()); // 打印输出的是?
答案是“Hello,World”。
因为object.getMessage()是方法调用,所以this指向的object。
二、回答猫的名字
function Pet(name) { this.name = name; this.getName = () => this.name; } const cat = new Pet('Fluffy'); console.log(cat.getName()); // 输出的是? const { getName } = cat; console.log(getName()); // 输出的是?
两个输出都是:“Fluffy”。
当一个函数被调用作为构造函数,该构造函数内等于所构造的对象。
this.name = name相当于构造函数中的表达式在构造name对象上创建属性。
而this.getName = () => this.name在构造函数上创建一个方法,而且它是一个箭头函数,所以this指向还是构造函数Pet。
在调用cat.getName()和getName()都是返回的this.name。
三、延时执行
const object = { message: 'Hello, World!', logMessage() { console.log(this.message); // 输出的是? } }; setTimeout(object.logMessage, 1000);
在延迟1秒后,打印输出的是 undefined 。
尽管setTimeout()函数将object.logMessage()用作回调,但它仍是作为常规函数,而不是作为函数调用。
在常规函数调用中,this是作为全局对象的,可以说是指向window。
那没有声明全局message参数,所以也就说明为什么输出的是undefined。
四、功能完善
const object = { message: 'Hello, World!' }; function logMessage() { console.log(this.message); // "Hello, World!" } // 怎么实现上述结果
实现的方法有三种:
const object = { message: 'Hello, World!' }; function logMessage() { console.log(this.message); // logs 'Hello, World!' } // 使用call()方法 logMessage.call(object); // 使用apply()方法 logMessage.apply(object); // 创建约束函数 const boundLogMessage = logMessage.bind(object); boundLogMessage();
五、问候和告别
const object = { who: 'World', greet() { return `Hello, ${this.who}!`; }, farewell: () => { return `Goodbye, ${this.who}!`; } }; console.log(object.greet()); // 输出的是? console.log(object.farewell()); // 输出的是?
输出的是“Hello,World”和“Goodbye,undefined”。
调用object.greet(),方法内部的greet()的this是指向object,因为greet()是一个常规函数,所以也就能调用到object中的who。
但是farewell()是箭头函数,因此箭头函数内部的this始终指向外部,也就是object的外部。
六、棘手的长度
var length = 4; function callback() { console.log(this.length); // 输出的是? } const object = { length: 5, method(callback) { callback(); } }; object.method(callback, 1, 2);
输出的是4.
callback()使用内部的常规函数进行调用method(),因为常规函数callback()在调用期间this等于全局对象,this.length等于window.length。
七、调用参数
var length = 4; function callback() { console.log(this.length); // 输出的是? } const object = { length: 5, method() { arguments[0](); } }; object.method(callback, 1, 2);
打印输出的是3.
obj.method(callback,1,2)调用时需要三个参数,callback,1和2。结果,arguments内部的特殊变量method()是具有以下结构的类似数组的对象:
{ 0: callback, 1: 1, 2: 2, length: 3 }
也就是:
arguments[0]() == callback() == this指向arguments == arguments.length == 3
所以输出了3.
八,概括
看完上面的七个问题,是不是对this有了更深刻的印象和理解呢。函数的调用是执行构成函数主体的代码,或者只是调用该函数。