一道JavaScript编程题的拓展

背景

鄙人前端小白,近日在刷种种算法/编程题,本日碰到一编程题,考点是apply,虽然说简朴,但在解题时发现了一个挺有意义的东东,特来分享一下。迎接列位大佬指导~

正文

话不多说,直接上问题:二次封装函数。

已知函数 fn 实行须要 3 个参数。请完成函数 partial,挪用以后满足以下前提:
1、返回一个函数 result,该函数接收一个参数
2、实行 result(str3) ,返回的效果与 fn(str1, str2, str3) 一致

哈哈,这题简朴!轻微学过js的朋侪就能够写出来:

function partial(fn,str1,str2) {
    var result = function(str3) {
        return fn(str1,str2,str3);
    }
    return result;
}

这里用个call能够会显得有点逼格(笑),固然apply,bind也能到达一样的效果。

function partial(fn,str1,str2) {
    var result = function(str3) {
        return fn.call(null,str1,str2,str3);
    }
    return result;
}

不多停止,我们来看下一题,同样是二次封装函数:

完成函数 partialUsingArguments,挪用以后满足以下前提:
1、返回一个函数 result
2、挪用 result 以后,返回的效果与挪用函数 fn 的效果一致
3、fn 的挪用参数为 partialUsingArguments 的第一个参数以后的悉数参数以及 result 的挪用参数

emmmmm,传入的参数不牢固? 有了! 用arguments~

function partialUsingArguments(fn) {
  var _arguments = Array.prototype.slice.call(arguments,1)
  var result = function() {
    var newArguments = _arguments.concat(Array.prototype.slice.call(arguments,0));
    return fn.apply(null,newArguments)
  }
  return result;
}

唔,彷佛也没什么难的,_arguments就是partialUsingArguments第一个参数后的一切参数构成的数组,将它和result的一切参数兼并起来,应用apply传入fn,ok~处理了!

诶诶?有意义的东西呢?这特么一点意义都没啊。
说出来你们能够不信,实在我看到这题的时刻,虽然我想到了用apply,但我并没有想到fn.apply(null,newArguments)。那我想到的是什么呢?

Function.prototype.call.apply

什么鬼?我也不晓得是在哪看过这东西(或许没看过),又彷佛是

Function.prototype.call.call

照样

Function.prototype.apply.apply

照样

Function.prototype.apply.call

彷佛都差不多,妈个鸡,尝尝就晓得了!

return Function.prototype.call.apply(fn,newArguments)
浏览器一跑,彷佛对了?不对!我传入的第一个参数怎样不见了?
Google之~ 噢~ 本来第一个参数被吃了。
本来Function.prototype.call.apply(fn,newArguments)同即是fn.call(a,b,c,...z) // newArguments = [a,b,c,…z],这里的…z不是ES6中的...rest哦,只是示意省略了中心的参数。

晓得了道理(并不晓得),那就好办了,我给newArguments数组的头部补一个元素上去不就好了~

newArguments.unshift(0);
Function.prototype.call.apply(fn,newArguments)

浏览器一跑——没缺点老铁!

完了吗?

并没有!

既然.call.apply能够用,那其他3个按理来讲也能用,何况这里多了一步对数组的操纵,能不能更文雅一点呢?(别的3个怎样用,观众老爷们内心有答案吗?)
本着 求知 以及 code less,do more 的精力,我对剩下的3种组合进行了深♂入的研讨。

剖析及结论以下

道理实在很简朴,Function.prototype.apply(call)实在就是一个函数,将视为一个团体,记作A。原式就能够够转换成:A.apply(参数)A.call(参数),然后进一步转换,参数1.A(参数2),什么参数、参数1、参数2的?
置信人人也看出来了,这里唯一的难点(?)就是参数。参数怎样写呢?

实在很简朴,apply就传数组,call就传一个序列。

applycall的区分人人一定晓得,我就不多说了。第一个参数一定是fn,这个没跑了。症结就在第二个参数上。

第二个参数,起首它形式上要看后一个apply/call,假如是apply,我们就传数组进去,假如是call,就传一个序列。然后它的内容就要看A了,也就是前一个apply/call,同理,假如是apply,就传数组参数,假如是call,就传序列参数

所以我们能够得出以下效果:

Function.prototype.apply.apply(fn,[null,newArguments])
Function.prototype.call.call(fn,null,...newArguments])
Function.prototype.apply.call(fn,null,newArguments])
//上面3式能够实际上即是
fn.apply(null,newArguments)
fn.call(null,...newArguments) //...为扩大运算符,...[arr] = arr[0],arr[1],...arr[n]
fn.apply(null,newArguments)

绕了一大圈,又回来了~ :)
而上面的Function.prototype.call.apply也能够改写成:

    Function.prototype.call.apply(fn,[null,...newArguments])

从而减少了对数组newArguments的操纵。

写在末了

第一次写文章(水贴),非常慌张,删了改,改完了删,总以为写的不好、非常烦琐。
能够会有人以为毫无意义,但我以为这个却是能够作为一道面试题。

请在填写空缺内容使等式建立:
fn.apply(null,args) = Function.prototype.apply.apply(_____)

假如真的有人碰到,请回来点赞^ ^
也愿望此文能若干协助到前端新人,人人一同进修,提高!
那里如果写不好能够直说!协助我提高。感谢!
不空话了,
完。

    原文作者:HaHa
    原文地址: https://segmentfault.com/a/1190000010244861
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞