数组有一个 Array.prototype.concat 函数,用于拼接数组。但他的用法非常奇异

1.同时支持输入元素和数组,有歧义

  1. [1,2].concat(3,4) // [1,2,3,4]
  2. [1,2].concat([3,4]) // [1,2,3,4]
  3. // 输出结果是一样的,会有隐藏的bug。如果元素是数组,无法确定输入的数组是元素还是待拼接的数组。
  4. // 即若想得到[1,2,[3,4]],就需要写成[1,2].concat([[3,4]])

2.是通用函数,可以拼接非数组

根据 ECMAScript 规范所说:concat被设置成通用函数,当this不是array时,亦可以执行。
image.png
如下,通过call可以执行非数组,但不能操作类数组对象arguments(slice可以操作)、纯对象 {0: 99, length: 1} (push可以操作)。

  1. [].concat.call({name: 'lily'}, [1,2])
  2. // [{name: 'lily'}, 1, 2]
  3. const arr = {0: 1, 1:2, length: 2}
  4. [].push.call(arr, 3)
  5. arr // {0: 1, 1: 2, 2: 3, length: 3}
  6. function slice () {
  7. return [].slice.call(arguments, 0, 1)
  8. }
  9. slice(1,2,3,4,5) // [1]