前言
能点进这篇文章的掘友,应该都是因为看了这道面试题吧。
123['toString'].length + 123 = ?
这道题的本意可能是想考察 Number
重写了 toString
方法,可以通过传递参数改变数字的进制
console.log((10).toString()) // 10
console.log((10).toString(2)) // 1010
这算一个蛮实用的知识点,但几乎所有的人,都是栽在了函数的 length
上,而且这道题本身,也存在着问题。
很多人应该是第一次听说,函数还有个 length
属性?
本文会向你详细介绍这个属性,并指出这道面试题的败笔。
ES 标准
在 ECMAScript 标准中,确实规定了函数的 length
属性,是函数形参的个数。
我们来测试一下:
const fun1 = () => {}
const fun2 = (a) => {}
const fun3 = (a, b) => {}
console.log(fun1.length) // 0
console.log(fun2.length) // 1
console.log(fun3.length) // 2
可以看出,普通形参的函数表现是正常的,有几个形参,函数的长度就是多少。
特殊参数
但是,ES6 新增了两种参数:默认参数和剩余参数,看看这两种参数对结果的影响。
const fun1 = (a, b = 1) => {}
const fun2 = (a, b = 1, c) => {}
const fun3 = (a, ...b) => {}
console.log(fun1.length) // 1
console.log(fun2.length) // 1
console.log(fun3.length) // 1
标准中对此并未说明,我们只能通过测试得出结果:
函数的长度取决于第一个默认参数之前的参数;剩余参数不计算在函数的长度中。
看到这你或许会疑惑,Number
原型上的 toString
方法可以不加参数调用的呀,不算默认参数吗?
对,我也很疑惑,这就是这道面试题的败笔了,请接着往下看。
败笔
上面咱们得出的规则,并不适用于原生函数。
原生函数指的就是 JS 内部自己定义的函数,它们在控制台打印时函数体显示为 [native code]
console.log(Number.prototype.toString) // ƒ toString() { [native code] }
console.log(Array.prototype.slice) // ƒ slice() { [native code] }
而它们的 length
就很奇怪了
console.log(Number.prototype.toString.length) // 1
console.log(Array.prototype.slice.length) // 2
console.log(Array.prototype.map.length) // 1
console.log(Array.prototype.forEach.length) // 1
这四个函数都是有默认参数的,而前两个将默认参数算进了 length
中,后两个则不算。
原生函数的长度并没有统一的规则!除非你亲自测试过这个函数的 length
,不然形参是否参与计算,根本无从推断。
谁会没事把原生函数的长度都测一遍啊,这就是面试题的败笔!
可能许多人不知道 map 和 forEach 还有第二个参数,用以指定回调函数内部的 this 指向,前提是传入的回调函数不是箭头函数。
离谱
有关函数的长度,还有更为离谱的现象,在此展示。
原生函数中的奇葩
看看 push
与 Function
这两个函数的长度
console.log(Array.prototype.push.length) // 1
console.log(Function.length) // 1
你知道它们调用时的参数是什么样的吗?
Array.prototype.push (...items)
Function (p1, p2, … , pn, body)
只能说,我不理解函数的 length
有何意义?
有关这两个方法可以详见 push 与 [Function](https://tc39.es/ecma262/multi...
) 的标准。
删除函数的 length
目前的 ES 标准中, 函数的长度是可配置的,然后就出现了下面的 bug?
const fun = (a, b) => {}
console.log(fun.length) // 1
delete fun.length
console.log(fun.length) // 0
备注:在之前的 ES 版本中,函数的长度是不可配置的。
结语
在我们的实际开发中,根本用不到函数的 length
,这个属性设计的毫无意义,本文就请当个乐子看看就好了,或者在他人面前装个13~
如果喜欢或者有所启发,欢迎点赞关注,鼓励一下新人作者。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。