退出历史的舞台的arguments

2,411 阅读3分钟

arguments已经退出了历史的舞台,仅以此文缅怀它曾经的贡献。

非箭头函数的两个隐藏参数:arguments、this。它们虽然祸害了不知道多少jser,但是在那个年代它们在JS中却有着其必要性,有着举足轻重的作用。这篇所说的arguments就在一些场景不可替代。

首先,让我们来了解一下先来简单回顾一下arguments。

什么是arguments

一个函数的隐藏参数,一个类数组, 一个可以偷偷把参数的值给修改的老王。 通过下面代码片段就可以展示出了它的功能:


!function(a) {
  console.log(arguments[0])
  if (a === 'a1') {
    arguments[0] = 'a2' 
  }
  if (a === 'a2') {
    arguments.callee('a3')
  }
}('a1')

!function(a) {
  console.log(a) // 'a1'
  console.log(arguments[0] === a) // true
  
  a = 'a2'
  console.log(arguments[0]) // 'a2'
  
  arguments[0] = 'a3'
  console.log(a) // 'a2'

}('a1')

第一段代码中arguments[0]先后打印'a1', 'a2'。从这段代码可以总结一下它的作用:

  1. 是函数的隐藏参数。和当前的作用域绑定
  2. 是一个类数组。既有[0]这样的用法,还有.callee这样的方法
  3. .callee可以直接执行当前作用域的函数

第二段代码代表了,arguments和a是映射关系。

每一个都槽点:

  1. arguments和a是映射关系,你改我,我改你,代码一多就乱七八糟。
  2. .callee方法更逗比了,为什么我不直接给立即执行函数加一个函数名呢?匿名函数显得高级一些?
  3. 类数组最无语了,把无用的.callee方法给删除掉,变成数组能咋滴?forEachmap都用不了

arguments没有可迭代的对象

image.png

当然,吐槽一时爽,一直吐槽一直爽。毕竟Brendan Eich当初创造出来的时候面临的问题简单,而且时间也短,有这样那样的历史包袱很正常。

那些制定语法标准的大佬自然也知道这些问题。所以ES6带来了function(...ary), ary可是真数组,Array有的方法它都能够使用。有了参数的解构方法,arguments才得以退出js的舞台,当然尾大不掉,为了照顾那些老的项目并没有赶尽杀绝,它依旧可以使用,只是有了替代而已。

弱化arguments

ES6开始弱化arguments的作用。

通过一下手段:

  1. 箭头函数没有arguments这个2.2 隐式参数
  2. 形参可以有默认值
  3. 数组结构方式
function test(...arr) {
  console.log(arr) // [[1, 3], 'c'] 是一个二维数组
}
test([1, 3], 'c')

其实从ES5中就有严格模式来限制arguments的操作. 不让它有共享,不让它有映射关系.

function test(a = 100) {
  arguments[0] = 10
  
  console.log(a, arguments[0])
}

test(1) // 1, 10

这里输出1, 和10。 arguments并没有改变a的值

但是如果取消掉默认值的话,打印的结果就是 10, 10。 说明ES6的语法刻意的屏蔽掉arguments映射形参的作用。

当然,如果在ES5中使用严格模式的话,也是能够把argument作用给屏蔽掉的,如下代码片段:

function test3(a) {
  "use strict"
  arguments[0] = 10
  
  console.log(a, arguments[0])
}

test3(1)

甚至于,arguments.callee 在严格模式下面也会报错了.

image.png

“开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 10 天,点击查看活动详情