【问题标题】:What exactly `Function.prototype.length` means?`Function.prototype.length` 到底是什么意思?
【发布时间】:2017-07-20 18:07:18
【问题描述】:

有一个Function.prototype.arity 属性用于获取函数期望的参数数量。现在它已经过时了(从 JS 1.4 开始),同样的目标有 Function.prototype.length

但是最近我在文档中发现了一篇关于Array.prototype.reduce 方法的文章。它清楚地表明该方法的属性length 等于1

reduce 方法的 length 属性为 1。

这篇确切的文章有一个带有多个参数的标题,其中有两个:

Array.prototype.reduce ( callbackfn [ , initialValue ] )

callbackfninitialValue(可选)。

所以我不清楚length 属性的确切用途。
如果它是用来给开发者提供有用信息的,那么它实际上并没有。
如果它只是一个技术自动生成的属性,只是表示函数定义中的参数数量,那为什么不保持它的一致性呢?

【问题讨论】:

  • ECMAScript 5.1, Section 15.3.5.1, length: "length 属性的值是一个整数,表示函数期望的“典型”参数数量。但是,语言允许使用其他数量的参数调用函数。"
  • reduce 需要一个参数(必需的),另一个是可选的,所以不计算在内!
  • 至少你需要一个回调函数来运行reduce。
  • 旁注:length 属性是单个实例的属性,而不是原型属性; specFunction.prototype 具有 length 属性的唯一原因是 Function.prototypeFunction 实例(主要是出于历史原因)。

标签: javascript ecma262


【解决方案1】:

Array.prototype.reducelength 为 1,因为第二个参数是可选的。*

所以我不清楚length 属性的确切用途。

告诉开发者在第一个具有默认值的参数(如果有)或其余参数(如果有)之前有多少个声明的参数,以参数列表中最早的那个为准。或者the spec puts it:

length 属性的值是一个整数,表示函数期望的参数的典型数量。

确切的算法在the spec's Static Semantics: ExpectedArgumentCount section

如果它是用来给开发者提供有用信息的,那么它实际上并没有。

嗯,这是一个见仁见智的问题。 :-)

当你有一种像 JavaScript 这样的语言时,函数只能表达一个期望,但可以用更少或更多的参数调用,特别是当你添加默认参数值和剩余参数的概念时,函数的arity 也就不足为奇了是一个有点软的概念。

一些有趣的例子:

function ex1(a) { }             // length is 1, of course
function ex2(a, b = 42) { }     // length is 1, `b` has a default
function ex3(a, b = 42, c) { }  // length is 1, `b` has a default and
                                // `c` is after `b`
function ex4(a, ...rest) { }    // length is 1 yet again, rest parameter doesn't count

* 在 ES5 中,它在 JavaScript 中的声明是:

function reduce(callback) {
    // ...
}

...然后它将使用arguments.length 来确定您是否应该使用initialValue

在 ES2015+(又名“ES6”+)中,要么仍然是这样,要么是这样:

function reduce(callback, ...args) {
    // ...
}

...并使用args.length查看是否有初始值。

或者可能是这样的:

const omitted = {};
function reduce(callback, initialValue = omitted) {
    // ...
}

...然后使用initialValue === omitted 来了解您是否提供了初始值。 (initialValue 的默认值不能是 undefinednull 或类似的,因为函数必须根据参数是否提供 [不是它的值] 进行分支。但是我们可以使用对象标识来做到这一点.)

【讨论】:

  • 所有这些,可能除了其余的参数,在 JavaScript 中都不是很直观。
  • @DmitryParzhitsky:是的,好吧,这又是一个见仁见智的问题。最初没有计算的默认参数值让我感到惊讶,但必须记住它们是在首次创建 20 年后才添加到该语言中的。 TC39(管理该语言的委员会)在不破坏 15 年前编写并仍在使用中的东西的情况下推动 JavaScript 向前发展是一项非常的工作。在我们使用语言之前默认参数的常见习语导致它们不被计算在内,所以我猜这就是他们这样做的原因。 :-)
猜你喜欢
  • 2017-08-07
  • 2014-09-23
  • 2014-07-25
  • 2012-09-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多