IDC

七个关于"this"面试题,你能回答上来吗?

作者:admin 2021-04-30 我要评论

本文已经过原作者 Shadeed 授权翻译。 在JavaScript中,this 表示函数调用上下文。this难点在于它有一个复杂的行为,这也是面试中经常被考的点。 本文列举7个关...

在说正事之前,我要推荐一个福利:你还在原价购买阿里云、腾讯云、华为云服务器吗?那太亏啦!来这里,新购、升级、续费都打折,能够为您省60%的钱呢!2核4G企业级云服务器低至69元/年,点击进去看看吧>>>)

本文已经过原作者 Shadeed 授权翻译。

在JavaScript中,this 表示函数调用上下文。this难点在于它有一个复杂的行为,这也是面试中经常被考的点。

本文列举7个关于this有趣的面试问题:

  • 问题1:变量 vs 属性
  • 问题2:Cat 的名字
  • 问题3:延迟打招呼
  • 问题4:人工方法
  • 问题5:问候和告别
  • 问题6:棘手的 length
  • 问题7:调用参数

问题1:变量 vs 属性

下面的打印结果是啥:

  1. const object = { 
  2.   message: 'Hello, World!'
  3.  
  4.   getMessage() { 
  5.     const message = 'Hello, Earth!'
  6.     return this.message; 
  7.   } 
  8. }; 
  9.  
  10. console.log(object.getMessage()); // ?? 

答案:'Hello, World!'

object.getmessage()是一个方法调用,此时的 this 表示 object。

方法还有一个变量声明const message = 'Hello, Earth!'。这个变量都不会影响this.message的值。

问题2:Cat 的名字

下面代码打印什么:

  1. function Pet(name) { 
  2.   this.name = name
  3.  
  4.   this.getName = () => this.name
  5.  
  6. const cat = new Pet('Fluffy'); 
  7.  
  8. console.log(cat.getName()); // What is logged? 
  9.  
  10. const { getName } = cat; 
  11. console.log(getName());     // What is logged? 

答案:'Fluffy' 和 'Fluffy'

当函数作为构造函数new Pet('Fluffy')调用时,构造函数内部的this等于构造的对象

Pet构造函数中的this.name = name表达式在构造的对象上创建name属性。

this.getName = () => this.name在构造的对象上创建方法getName。而且由于使用了箭头函数,箭头函数内部的this值等于外部作用域的this值, 即 Pet。

调用cat.getName()以及getName()会返回表达式this.name,其计算结果为'Fluffy'。

问题3:延迟打招呼

下面代码打印什么:

  1. const object = { 
  2.   message: 'Hello, World!'
  3.  
  4.   logMessage() { 
  5.     console.log(this.message); // What is logged? 
  6.   } 
  7. }; 
  8.  
  9. setTimeout(object.logMessage, 1000); 

答案:1秒后,打印 undefined。

尽管setTimeout()函数使用object.logMessage作为回调,但仍将object.logMessage用作常规函数,而不是方法。

在常规函数调用期间,this等于全局对象,即浏览器环境中的 window。

这就是为什么logMessage方法中的 this.message等于 window.message,即undefined。

问题4:人工方法

如何调用logMessage函数,让它打印 "Hello, World!" ?

  1.  message: 'Hello, World!' 
  2. }; 
  3.  
  4. function logMessage() { 
  5.   console.log(this.message); // "Hello, World!" 

答案:

至少有 3 种方式,可以做到:

  1.  message: 'Hello, World!' 
  2. }; 
  3.  
  4. function logMessage() { 
  5.   console.log(this.message); // logs 'Hello, World!' 
  6.  
  7. // Using func.call() method 
  8. logMessage.call(object); 
  9.  
  10. // Using func.apply() method 
  11. logMessage.apply(object); 
  12.  
  13. // Creating a bound function 
  14. const boundLogMessage = logMessage.bind(object); 
  15. boundLogMessage(); 

问题5:问候和告别

下面代码打印什么:

  1. const object = { 
  2.   who: 'World'
  3.  
  4.   greet() { 
  5.     return `Hello, ${this.who}!`; 
  6.   }, 
  7.  
  8.   farewell: () => { 
  9.     return `Goodbye, ${this.who}!`; 
  10.   } 
  11. }; 
  12.  
  13. console.log(object.greet());    // What is logged? 
  14. console.log(object.farewell()); // What is logged? 

答案: 'Hello, World!' 和 'Goodbye, undefined!'。

当调用object.greet()时,在greet()方法内部,this值等于 object,因为greet是一个常规函数。因此object.greet()返回'Hello, World!'。

但是farewell()是一个箭头函数,箭头函数中的this值总是等于外部作用域中的this值。

farewell()的外部作用域是全局作用域,它是全局对象。因此object.farewell()实际上返回'Goodbye, ${window.who}!',它的结果为'Goodbye, undefined!'。

问题6:棘手的 length

下面代码打印什么:

  1. var length = 4; 
  2. function callback() { 
  3.   console.log(this.length); // What is logged? 
  4.  
  5. const object = { 
  6.   length: 5, 
  7.   method(callback) { 
  8.     callback(); 
  9.   } 
  10. }; 
  11.  
  12. object.method(callback, 1, 2); 

答案: 4

callback()是在method()内部使用常规函数调用来调用的。由于在常规函数调用期间的this值等于全局对象,所以this.length结果为window.length。。

第一个语句var length = 4,处于最外层的作用域,在全局对象 window 上创建一个属性length。

问题7:调用参数

下面代码打印什么:

  1. var length = 4; 
  2. function callback() { 
  3.   console.log(this.length); // What is logged? 
  4.  
  5. const object = { 
  6.   length: 5, 
  7.   method() { 
  8.     arguments[0](); 
  9.   } 
  10. }; 
  11.  
  12. object.method(callback, 1, 2); 

答案: 3

obj.method(callback, 1, 2)被调用时有3个参数:callback, 1和2。结果,method()内部的参数特殊变量是如下结构的数组类对象:

  1.   0: callback, 
  2.   1: 1,  
  3.   2: 2,  
  4.   length: 3  

因为arguments[0]()是arguments对象上的回调的方法调用,所以回调内部的参数等于arguments。所以 callback()中的this.length与arguments.length相同,即3。

~ 完,我是小智,我们下期见!

作者:Shadeed 译者:前端小智 来源:dmitripavlutin原文:https://dmitripavlutin.com/javascript-this-interview-questions/


本文转载自网络,原文链接:https://mp.weixin.qq.com/s/4aH9s-LEsRE4vZWijN3PjA

版权声明:本文转载自网络,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。本站转载出于传播更多优秀技术知识之目的,如有侵权请联系QQ/微信:153890879删除

相关文章
  • 百信银行正式开业!启用域名aibank.com

    百信银行正式开业!启用域名aibank.com

  • .site域名会引渡重磅交易!三声四数换

    .site域名会引渡重磅交易!三声四数换

  • “化石”56000元被秒,五数.com 78888

    “化石”56000元被秒,五数.com 78888

  • ICANN公布5月国际域名动态:阿里云、西

    ICANN公布5月国际域名动态:阿里云、西

腾讯云代理商
海外云服务器