在一篇博客中看到的问题,博主提出来之后也没解答出来,求解。function f1(x){
    f2();
    console.log(x);//2
    console.log(arguments[0]);//2
}function f2(){
    console.log(f2.caller.arguments) // [1]
    f2.caller.arguments[0]=2;
    console.log(f2.caller.arguments)// [2]
}f1(1);奇怪的是下面,把console.log(arguments[0]);删了之后是下面这个结果!!!function f1(x){
    f2();
    console.log(x);//1
}function f2(){
    console.log(f2.caller.arguments) // [1]
    f2.caller.arguments[0]=2;
    console.log(f2.caller.arguments)// [1]
}f1(1);加上一句var arg = arguments;又恢复到原来的情况了。function f1(x){
    f2();
    console.log(x);//2
    var arg = arguments;
}function f2(){
    console.log(f2.caller.arguments) // [1]
    f2.caller.arguments[0]=2;
    console.log(f2.caller.arguments)// [2]
}f1(1);似乎必须“声明”一下才能写,要不然就是只读的?

解决方案 »

  1.   

    arguments还真没研究过。。不过测试发现IE下面是正常的,就算不 console.log(arguments[0])也会改变f1的参数,而FF与chrome都需要arguments[0]调用一下
    我估计FF与chrome是当创建动态作用域的时候如果发现函数里面没有调用arguments[0],就不会将arguments与实参的绑定,而IE下面就算没调用,当创建动态作用域时都会与实参绑定。纯粹推测
      

  2.   

    浏览器厂商在实现函数临时属性arguments时,实现方式各有不同。arguments是属于运行期间临时创建的,创建时机存在2种:
    1:函数一被执行就创建。
    2:只有使用到arguments属性时才被创建以上属个人观点。设想一下,假如由我们来实现创建arguments临时属性,创建时机也就这么几种。
      

  3.   

    我觉得在IE,FF,chrome中创建动态作用域的时候arguments已经创建了,从楼主的例子,就算在f1中没有调用arguments,在f2中也能找到就证明了。大家没有对arguments的传值方式有疑问的么?明明我穿的参数是一个数值,是大家都知道数值是值传递,为什么我改arguments[0] = 111;的时候x的值也会变成111,按理是不会的,简单例子实现
    var arr = [1,2,3,4],
        num = arr[2];
    arr[2] = 111;
    alert(num); //3
    很明显吧?就算我们改变了数组某个索引下面的值,都不会改变num,因此我们可以推测出,引擎会将arguments与实参做一个类似引用绑定的操作,实参或者实参对应的arguments,只要其中一方改变了,另一方也会改变请看两个例子,与楼主的例子差不多,不过这两个例子传进去的是一个对象
    var obj = {name:"123"}function f1(x){    
        f2();    
        console.log(x);//222     
        console.log(arguments);//["222"]   
    }function f2(){
        console.log(f2.caller.arguments) // [Object { name="123"}]
        f2.caller.arguments[0].name = "222"
        console.log(f2.caller.arguments) // [Object { name="222"}]
        f2.caller.arguments[0] = "222"
    }f1(obj);
    var obj = {name:"123"}function f1(x){    
        f2();    
        console.log(x);//Object { name="222"}     
    }function f2(){
        console.log(f2.caller.arguments) // [Object { name="123"}]
        f2.caller.arguments[0].name = "222"
        console.log(f2.caller.arguments) // [Object { name="222"}]
        f2.caller.arguments[0] = "222"
    }f1(obj);这两个地址是FF,chrome中的情况,当在IE下(大家请将console.log改成alert),2个写法的结果都是一样的所以我推测在FF,chrome中,当在创建活动作用域时,引擎发现有arguments的调用,就会将arguments与实参做之前所说的类似引用的绑定,只要一方改变了,另一方也改变,但当发现没有arguments调用时,FF,chrome不会做这个绑定,arguments里面的纯粹是实参的引用而已,就算我在f2函数里面获取到f1的arguments,对其对应的索引下的引用做改变,f1的arguments也不会改变,除非是对引用的副本做修改,(符合引用与值传递的原理)请参考我给出的2个例子。
    但在IE中,无论你有没调用arguments,引擎都会做绑定,就会出现IE与 FF,chrome不同的情况出现了其实FF,chrome这样做也有好处,毕竟arguments在实际中用得比较少,当没调用的时候,确实没必要做绑定,因为做这种绑定,肯定会开辟内存进行存储,也算是一个性能优化吧。
    以上就是我的推测
      

  4.   

    刚测试了一下,没发现楼主的问题function f1(x){
        f2();
        console.log(x);
        console.log(arguments[0]); // 这句话注释与不注释,执行结果完全一样。
    }function f2(){
        console.log(f2.caller.arguments)
        f2.caller.arguments[0]=2;
        console.log(f2.caller.arguments)
    }f1(1);firefox运行结果都是:firefox 3.6.23
    [1]
    [2]
    2IE 8运行结果都是:
    [object Object]
    [object Object]
    2
      

  5.   


    IE8下应该 console.log(f2.caller.arguments[0])
      

  6.   

    caller?? 印象中好像是一个被删掉的属性,,连AS 在 3.0版本时也删掉了caller