Home  >  Q&A  >  body text

javascript - 关于JS的算法题

function largestOfFour(arr) {
  return arr.map(Function.apply.bind(Math.max, null));
}
largestOfFour([[4, 5, 1, 3], [13, 27, 18, 26], [32, 35, 37, 39], [1000, 1001, 857, 1]]);

这Function.apply.bind(Math.max, null) 该怎么理解??

怪我咯怪我咯2771 days ago338

reply all(4)I'll reply

  • 伊谢尔伦

    伊谢尔伦2017-04-11 12:59:54

    假如直接这样

    function largestOfFour(arr) {
      return arr.map(Math.max);
    }

    输出一定是四个NAN
    因为Math.max的参数不能是数组,一定是Math.max(1,2,3)这样的格式
    所以传给map的callback一定是可以处理数组的每一项由[1,2,3]变成1,2,3
    来看函数:

    function largestOfFour(arr) {
      return arr.map(Function.apply.bind(Math.max, null));
    }

    单独拿出来看

    Function.apply.bind(Math.max, null)

    Function.apply里面的this被替换成Math.max,同时参数传过去null

    这时候arr里面的每一项数组作为参数传递给Function.apply,由Math.max处理,而数组当做apply的第二个参数正好处理

    不知道我解释的清不清晰~~

    reply
    0
  • 巴扎黑

    巴扎黑2017-04-11 12:59:54

    function largestOfFour(arr) {
      return arr.map(func);
    }

    largestOfFour(这个Four其实是多余的,因为并不一定得是4个元素,1-n个元素都行)这个函数目的在于求一个二维数组中每个一维数组中的最大值。

    那么我们正常思路是什么呢,首先,肯定会用到map,这样我们只需要编写一个函数,这个函数接受一个数组,并返回一个数组中的最大值。但是已经有现成的max函数了,他虽然能返回最大值,但是接收的并不是一个数组,而是一连串的数字。这不符合我们的应用场景,但是程序猿是懒惰的,于是我们想,能不能稍微改造下这个max函数,利用他产生一个函数,这个函数接收的参数变成一个数组,而不是一连串数字。
    自然,我们就想到了apply,因为他可以将一个数组作为arguments传给一个函数。简单的小测试如下:

    function func(v1, v2, v3) {
       console.log(v1 + ',' + v2 + ',' + v3);
    }
    
    func.apply(null, [1,2,3]); // 输出1,2,3

    所以我们可以写出这样

    
    return arr.map(function(ele) {return Math.max.apply(null, ele);});
    

    但是这样我们创建了一个匿名函数,我们还想简化怎么办(虽然我比较喜欢这种写法,看起来简单很多。。)

    好,现在确定下我们的目标,我们想得到一个函数。这个函数要完全基于Math.max,也就是函数体要相同(但我们不想要一个匿名函数去包裹他),这个时候我们就只能调用Function这个所有函数的父类了,通过他来创建函数。

    但是我们不能直接Function.apply(Math.max)这样就已经调用了max了,我们现在需要的是一个函数的引用,而不是调用他。于是我们想到了bind,他能返回一个函数的副本,并且能改变this指向。

    Function.apply.bind(Math.max, undefined, [2, 3, 4, 5, 6])()
    // or
    Function.apply.bind(Math.max, undefined)([2, 3, 4, 5, 6])

    即构建一个与Math.max函数体内容相同的函数,这里的undefined为Math.max里的this指向(bind的第一个参数为调用apply时的this指向,这里为Math.max,即构建一个与Math.max函数体内容相同的函数。第二个参数为追加在arguments之前的参数,如

    
    function aa(){console.log(arguments);}
    
    aa.bind(null, 22)(33); // 输出22, 33
    

    具体可以看看bind的用法这里)。

    [2, 3, 4, 5, 6]为调用Math.max时的arguments指向。

    上例中的[2, 3, 4, 5, 6]是调用map函数时参数列表中的第一个参数(第一个参数为数组中的每个值,在第一次调用的时候即是题目中的[4, 5, 1, 3])

    这样,就实现了我们想要的功能,即改造Math.max,利用他实现一个函数,这个函数接收一个数组作为参数,返回数组中的最大值。

    reply
    0
  • ringa_lee

    ringa_lee2017-04-11 12:59:54

    这么理解:

    function largestOfFour(arr) {
      return arr.map(function(val) {
          return Math.max.apply(null, val);
      });
    }

    确实有点绕儿

    reply
    0
  • PHP中文网

    PHP中文网2017-04-11 12:59:54

    https://segmentfault.com/q/10...
    看这里。

    reply
    0
  • Cancelreply