分享一道有意思的arguments笔试题 前言

你盼世界,我盼望你无bug。Hello 大家好!我是霖呆呆!
这篇文章很短…但绝对不是一篇水文…
主要是在评论区看到了,觉得是我们平常会忽略的一个小知识点而且笔试也有可能碰到,所以单独作为一篇文章来写,还请花个2分钟来看看吧,万一真给碰上了呢 😁。
(题目来源:掘友Lazzw,感谢该小伙伴的提出)
正题
题目是这样的:
var obj = { age: 18, foo: function (func) { func() arguments0 }} var age = 10 function temp () { console.log(this.age)}obj.foo(temp)复制代码
不买关子,咱先上答案:
10undefined复制代码
之前我们一直只在意函数中最常用的隐藏参数this,而这道题其实就考到了函数中隐藏的另一个参数arguments。
先简单说明一下arguments的作用再来看这道题吧。
arguments参数是传递给函数的所有参数的集合(类数组结构),例如下面这两个例子:
function test1 () { console.log(arguments)}function test2 (a) { console.log(a) console.log(arguments)}test1(1, 2)test2(1, 2)复制代码
执行结果为:
[1, 2]1[1, 2]复制代码
可以看到,不管你的函数中有没有形参,arguments都会获取到你调用函数时传递的所有实参。
(而且arguments只存在于普通函数中,window全局下和箭头函数中都不存在)
另外我们知道,传递给函数的参数也可以是一个函数,那么只要是参数,arguments就可以捕获到,就算你是一个函数也逃不了,比如这样:
function foo () { arguments0}function temp () { console.log(this)}foo(temp) // Arguments [ƒ temp()]复制代码
如上题,向foo()中传递了temp函数,并且使用arguments0调用它是可以执行的。
比较有意思的就是这里了,如果你是将temp当参数传递进去并且调用的话,就会发生隐式绑定丢失问题(类似《【建议👍】再来40道this面试题酸爽继续(1.2w字用手整理)》中的题目3.3),从而使函数内的this指向window:
function foo (fn) { fn()}function temp () { console.log(this)}foo(temp) // Window复制代码
但是这里我们是用arguments0这样的形式调用它,它里面的this指向的就不是window而是arguments本身了。
所以回到原题中:
var obj = { age: 18, foo: function (func) { func() arguments0 }} var age = 10 function temp () { console.log(this.age)}obj.foo(temp)复制代码
题目解析:

在使用obj.foo(temp)时,将temp函数当成了参数传递到foo中,这里我们知道func是发生了隐式绑定丢失的,所以导致第一次调用temp函数(也就是执行func()这段代码)的时候,temp内的this是指向window的,因此会打印出10。而传入进去的temp会被arguments所搜集,所以可以使用arguments0这样的形式调用。但是此时temp内的this就是arguments了,而在arguments内是没有age这个属性的,所以会打印出undefined。
为了验证这个想法💡,我们可以将题目改造一下:
var obj = { age: 18, foo: function (func) { func() arguments.age = 66 // 新增代码1 arguments0 }} var age = 10 function temp () { console.log(this) // 新增代码2 console.log(this.age)}obj.foo(temp)复制代码
我在题目中加了2行代码,一行是给arguments中添加了一个age属性,一行是将temp中的this打印出来。
现在来看看答案:
Window10Arguments [ƒ temp(), age: 66]66复制代码
果然执行结果和我们设想的一样,第二次调用temp时,temp内this的指向是arguments,并且我们给arguments里塞了个age,它也可以成功打印出来。

附加题
OK👌,霖呆呆最喜欢的事就是…
抢答时间!开始!
“买一送一”
没错啦,碰上了这道有意思的题你难道不想把它改造一下,增加增加难度吗?
[阴笑~]
上题!
var obj = { age: 10, foo: function (fn) { fn.call(this)() arguments0() arguments[0].call(this)() arguments0.call(this) }}var age = 20function temp () { return function () { console.log(this.age) }}obj.foo(temp)复制代码
我在temp中返回了一个匿名函数,并且将foo()接收到的参数用不同的方式调用它。
题目解析:

fn.call(this)()是最简单的了,看过呆呆this那篇文章的小伙伴应该都知道,fn.call(this)()使用.call(this)改变的是temp第一层函数中的this,但是最终调用那个匿名函数的还是window,所以会打印出20。(类似于this篇中的题目4.9)arguments0(),通过上面👆的正题我们知道arguments0中,也就是temp函数的第一层指向的是arguments对象,而调用temp返回的那个匿名函数的也还是window,就像是fn.call(this)()一样,所以打印出的也还是20。(做这类题你就想着一个函数中返回另一个函数,如果没用call/apply进行显式绑定的话,调用它的都是window)arguments[0].call(this)()和第二个一样,它使用.call(this)改变的是temp函数的第一层this指向,而调用匿名函数的也还是window,因此还是打印出20。arguments0.call(this),这里使用.call(this)改变的就是匿名函数内的this指向了,将它绑定为foo函数内的this,而我们知道,此时foo函数内的this是指向的obj,因为调用foo的是obj,所以会打印出10。
(以上👆提到的this篇链接为:《【建议👍】再来40道this面试题酸爽继续(1.2w字用手整理)》)
后语
知识无价,支持原创。
参考文章:

《理解函数调用-arguments参数》
你盼世界,我盼望你无bug。这篇文章就介绍到这里。
好像没什么问题嘛~
都是之前看到过的知识点 😁。
不过如果第一眼看着感觉做不来的小伙伴也别觉得自己不行🙅‍♂️,实话实话,就算是我自己写的文章不回头看的话也会忘掉 😂,所以我这不是经常搞搞有意思的题来帮我们一起巩固巩固嘛 😁,如果你都做的来的话,那很棒棒哦 👍。
(这个时间点写文章别和我老大举报我啊,我这是为了提高全中国前端工程师的JS水平)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值