js的arguments分析

首先看一段代码

    function test(x) {
        x=2 //or set arguments[0]=2;
        console.log(x,arguments[0]);
    }
    test(1)

执行结果中可以发现,argument和函数的参数列表中的变量是有关联的,这里假设函数的实参和形参个数是一样的。这个结果的背后到底是怎么回事,看了一下es5的arguments文档,尝试分析一下这个问题。
根据文档,当执行一个函数的时候,首先要执行CreateArgumentsObject 这个函数,并且把
1.当前执行的函数(也就是函数指针)fn
2.执行函数时用户实际传进来的参数列表args
3.函数声明中的实参列表名names
4.函数的变量环境对象env
这四个参数传进去,然后在CreateArgumentsObject 里,首先用Object函数创建一个空的对象obj,然后先往这个对象里挂载一些属性,其中包括但不限于:
1.设置该对象的Class为Arguments(这个我们用Object.prototype.toString.Call(arguments)可以看到)
2.设置该对象的构造函数为Object(通过arguments.constructor可以看到)
3.设置length为args的长度。
4.设置原型为Object.prototype
属性都是通过defineOwnProperty函数设置的,然后迭代实参列表,把每一个实参元素存起来,不过,这个并不仅存储在obj对象里。还重新生成一个对象parameterMap来存储,每一步具体的操作为:
1.把实参元素存储到obj里。
2.判断当前的索引是否小于函数fn实参变量names的长度,如果是就把实参元素存储一份到parameterMap里,并且设置描述符为{[[Set]]: p, [[Get]]: g, [[Configurable]]: true},es5说到这句话Let g be the result of calling the MakeArgGetter abstract operation with arguments name and env,也就是说p,g是一个用函数生成的函数,并且存在一个闭包,以后访问的时候是去访问env里面的值。到这里我们还没看出什么问题,arguments对象看起来差不多是这样的


arguments = {
Class: 'Aarguments',
constructor: Object,
0: 'hello',
1: 'world',
length: 2
.
.
.
ParameterMap: {
0: getter/setter
1: getter/setter
}
}
接着es5里说到了重点,原话The [[Get]] internal method of an arguments object for a non-strict mode function with formal parameters when called with a property name P performs the following steps,具体的可以看文档,其中说到了当访问arguments的属性时,会调用内部的arguments的get方法,这个方法会到ParameterMap对象里面找值,所以这里就会用到getter/setter,所以不管我们操作的变量是arguments[0],还是x,对应的值都是env里的那个变量,也就是arguments[0]和x共享了一个值,所以他们的操作会互相影响。
文档最后也提到,因为这种关联是进入函数时建立的,所以我们可以通过删除后重定义去解绑,上面的这些是基于非严格模式的,严格模式下他两的独立的,不会相互影响。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值