Math.min.apply(0, array) - why?

37

我刚刚在 JavaScript 代码(Raphaël.js)中找到了以下行(略有改动翻译):

Math.min.apply(0, x)

其中x是一个数组。你为什么要这样做呢?这种行为似乎是“从数组x中取最小值”。


Math.min.apply(this, x) 也可以。 - kennebec
今天更简短、更清晰的写法是:Math.min(...x) - JonasV
4个回答

39

我在发布自己的问题时意识到答案:这是JavaScript中获取数组 x 最小值最简洁的方法。第一个参数完全是任意的;我认为 0 会让人感到困惑,因为代码直观地表示“取 0 和 x 中的最小值”,这绝对不是真的。使用 Math 对象更有人类可读性,但 Raphael.js 的作者痴迷于代码缩小,0 比较短(只有三个字节)。

请参阅http://ejohn.org/blog/fast-javascript-maxmin/

出于可读性方面的考虑,我强烈建议人们停止这样做,而是定义一个类似以下结构的函数:

function arrayMin(arr) { return Math.min.apply(Math, arr); };

12
值得注意的是,Raphael代码中的“0”代表Math.min执行的作用域。之所以“应该”使用Math,是因为这是通常调用方法时该方法的本地/自然作用域。使用零可能相当于null,在那里等同于全局对象(window)。假设该方法不需要访问Math对象的内部状态,则这样做没有问题,这可能是一个安全的假设,但仍是一个假设。如果可以避免,请不要使用此模式。正如Trevor所指出的,应该使用Math。 - Ben Zotto
10
以上内容需更正:在此处使用零并不等同于null。这在语义上很荒谬,并导致作用域成为代表零的Number对象,基本上是毫无价值的。这可以最大程度地减少字符计数,但仍对“min”的内部工作方式做出了假设。 - Ben Zotto
1
代码压缩?这真的是一个词吗? :) - President James K. Polk
33
@GregS,这个过程曾经被称为使用各种编码技术和自动化代码处理工具将要发送给客户端的文件大小缩减到合理最小值。然后它被简称为uvasctaacpttrtftwbsttcttsras。缩写的发音自然演变成了单词minification。 - jball
1
谢谢quixoto,也感谢jball带给我的笑声。我现在觉得自己更聪明了。 - President James K. Polk

14

原因是这样的:

  • 您的输入x是一个数组

  • Math.min()的签名不接受数组,只接受逗号分隔的参数。

  • 如果您使用了Function.prototype.call(),它几乎具有相同的签名,只是第一个参数是this上下文,即谁在“调用”。

    • 示例:Math.min.call(context, num1, num2, num3)
  • context仅在函数内部引用this时才有影响,例如:您可以在数组上调用的大多数方法:Array.prototype.<method>会在方法内部引用this(点左侧的数组)。

  • Function.prototype.apply()call()非常相似,只是它现在在context之后需要一个数组,而不是以逗号分隔的参数。

    • Function.prototype.call(context, arg1, arg2, arg3)
    • Function.prototype.apply(context, [arg1, arg2, arg3])
  • 您放置的作为第一个参数的0null只是一个占位符。


1

你能详细解释一下第一个参数吗?我尝试了以下代码:var numbers = [5, 6, 7, 2, 3]; var max1 = Math.max.apply(4, numbers); var max2 = Math.max.apply(9, numbers); var max3 = Math.max.apply(null, numbers); 但我没有看到max1、max2和max3的不同结果。那么,如何在我的例子中获得不同的结果呢? - Hoang
只想提一下,根据链接,在非严格模式下才能使用 null。 - Justin Meiners

0
这里是一个示例,在这个时区中,我们可以获取给定年份的最大和最小时区偏移量。它返回一年中的两个变化,以考虑夏令时和标准时间。(例如在问题的时区中,ST = 300,DST = 360)。
   var arr = [];
   for (var i = 0; i < 365; i++) {
       var d = new Date();
       d.setDate(i);
       var newoffset = d.getTimezoneOffset();
       arr.push(newoffset);
   }
   var DST = Math.min.apply(null, arr);
   var nonDST = Math.max.apply(null, arr);
   tw.local.stInt = DST
   tw.local.edInt = nonDST

有人能告诉我调用 Math.min.apply(null, arr) 和 Math.min.apply(Math, arr) 的区别吗?null 调用上下文如何与 apply 协同工作?min 方法的本地上下文是 Math 对象,使用 Math 作为 apply 方法的第一个参数更有意义。 - user1176058

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接