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

作者:Shadeed
译者:前端小智
来源:dmitripavlutin

点赞再看,微信搜索**【大迁世界,B站关注前端小智】**这个没有大厂背景,但有着一股向上积极心态人。本文 GitHub https://github.com/qq44924588... 上已经收录,文章的已分类,也整理了很多我的文档,和教程资料。

最近开源了一个 Vue 组件,还不够完善,欢迎大家来一起完善它,也希望大家能给个 star 支持一下,谢谢各位了。

github 地址:https://github.com/qq44924588...

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

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

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

问题1:变量 vs 属性

下面的打印结果是啥:

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

答案:'Hello, World!'

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

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

问题2:Cat 的名字

下面代码打印什么:

1function Pet(name) { 2 this.name = name; 3 4 this.getName = () => this.name; 5} 6 7const cat = new Pet('Fluffy'); 8 9console.log(cat.getName()); // What is logged? 10 11const { getName } = cat; 12console.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:延迟打招呼

下面代码打印什么:

1const object = { 2 message: 'Hello, World!', 3 4 logMessage() { 5 console.log(this.message); // What is logged? 6 } 7}; 8 9setTimeout(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 4function logMessage() { 5 console.log(this.message); // "Hello, World!" 6}

答案:

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

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

问题5:问候和告别

下面代码打印什么:

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

下面代码打印什么:

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

答案: 4

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

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

问题7:调用参数

下面代码打印什么:

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

答案: 3

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

1{ 2 0: callback, 3 1: 1, 4 2: 2, 5 length: 3 6}

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

~ 完,我是小智,我要去刷碗了,我们下期见!


代码部署后可能存在的BUG没法实时知道,事后为了解决这些BUG,花了大量的时间进行log 调试,这边顺便给大家推荐一个好用的BUG监控工具 Fundebug

原文:https://dmitripavlutin.com/ja...

交流

文章每周持续更新,可以微信搜索「 大迁世界 」第一时间阅读和催更(比博客早一到两篇哟),本文 GitHub https://github.com/qq449245884/xiaozhi 已经收录,整理了很多我的文档,欢迎Star和完善,大家面试可以参照考点复习,另外关注公众号,后台回复福利,即可看到福利,你懂的。

点赞
收藏

评论区

加载中...

相关推荐

MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1

文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s

Oracle 分组与拼接字符串同时使用

SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(

手写Java HashMap源码

HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22

金三银四了,掌握 JS 这 36 个概念,助你一臂之力

作者:MahdhiRezvi译者:前端小智来源:dmitripavlutin点赞再看,微信搜索【大迁世界(https://mp.weixin.qq.com/s/sY9ufGGKfcdaAQ7KJQs3HA)】,B站关注【前端小智(https://space.bilibili.com/31089477)】这个没有大厂背景,但有着

2021 最顶级 React 组件库推荐

点上方蓝字关注公众号「前端从进阶到入院」作者丨MaxRozen译者丨王强策划丨小智AntDesign!(https://oscimg.oschina.net/oscnet/a85c35f23bd04e5da6a1e5e68a24119b.png)项目链接:AntDesignh

Android So动态加载 优雅实现与原理分析

背景:漫品Android客户端集成适配转换功能(基于目标识别(So库35M)和人脸识别库(5M)),导致apk体积50M左右,为优化客户端体验,决定实现So文件动态加载.!(https://oscimg.oschina.net/oscnet/00d1ff90e4b34869664fef59e3ec3fdd20b.png)点击上方“蓝字”关注我