在一篇博客中看到的问题,博主提出来之后也没解答出来,求解。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);似乎必须“声明”一下才能写,要不然就是只读的?
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);似乎必须“声明”一下才能写,要不然就是只读的?
我估计FF与chrome是当创建动态作用域的时候如果发现函数里面没有调用arguments[0],就不会将arguments与实参的绑定,而IE下面就算没调用,当创建动态作用域时都会与实参绑定。纯粹推测
1:函数一被执行就创建。
2:只有使用到arguments属性时才被创建以上属个人观点。设想一下,假如由我们来实现创建arguments临时属性,创建时机也就这么几种。
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在实际中用得比较少,当没调用的时候,确实没必要做绑定,因为做这种绑定,肯定会开辟内存进行存储,也算是一个性能优化吧。
以上就是我的推测
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
IE8下应该 console.log(f2.caller.arguments[0])