Javascript代理在Array.push()和按索引设置上的行为不同

Javascript代理在Array.push()和按索引设置上的行为不同,javascript,Javascript,我正在编写类似于以下代码片段的代码: 让arr=[]; 设arr_处理程序={ 集合:函数(目标、属性、值、接收者){ console.log('为'+target+'设置'+property+',值为'+value'); 目标[财产]=价值; 返回true; } }; 设arr\u proxy=新代理(arr,arr\u处理程序); arr_代理推送(1); //将0设置为值为1的 //设置值为1的1的长度 arr_proxy[1]=5; //将值为5的1设置为1 控制台日志(arr.len

我正在编写类似于以下代码片段的代码:

让arr=[];
设arr_处理程序={
集合:函数(目标、属性、值、接收者){
console.log('为'+target+'设置'+property+',值为'+value');
目标[财产]=价值;
返回true;
}
};
设arr\u proxy=新代理(arr,arr\u处理程序);
arr_代理推送(1);
//将0设置为值为1的
//设置值为1的1的长度
arr_proxy[1]=5;
//将值为5的1设置为1
控制台日志(arr.length);
//2
当数组值由索引设置时,为什么不调用代理设置器来设置长度

因为数组专用的动态
length
属性仅存在于代理内的
目标上

相反,
push
方法确实在其接收器上显式设置了
.length
属性。它不是由索引的赋值自动触发的。你可以试试看

const obj = { length: 0, push: Array.prototype.push };
obj.push(5)
console.log(obj) // { length: 1, 0: 5 }
您可以通过编写来实现与arr\u proxy.push(5)
调用相同的行为

const _len = arr_proxy.length;
arr_proxy[_len] = 5;
arr_proxy.length = _len + 1;

您的数组只有一个项,但您正在索引3上设置一个项。它将数组转换为稀疏数组,而稀疏数组不会更新长度。但是我在规范中找不到它。@如果我在索引1上设置了一个项目,它的行为方式是相同的。我更新了问题是的,我的分析/结论是错误的。我不确定。我会留下我的评论,这样其他人就不会跟我说同样的话了。但问题是,为什么在分配给索引时setter不会自动触发
length
对于仅在目标上存在的数组是特殊的,在这两种情况下,我是通过
push
还是通过索引添加值,但由于某种原因,它仅在通过
push()赋值时由包装器设置。
@aryndin push不仅添加值。Push还显式写入
.length
属性(即使这在数组对象上是不必要的,因为数组对象已经具有正确的长度)。@aryndin在分配给
[1]
期间,不会触发
长度设置器,因为您没有分配给
.length
。当您访问
.length
属性时,
length
getter随后将重新计算当前长度。它不是
push()
,因此应该考虑到不需要显式设置数组的长度?@aryndin否,
push
方法,它不需要数组-请参见我的答案中的示例,其中包含
obj
,它没有magic
.length
,并且仍然有效。(我并不是说引擎在数组上调用时不会对
push
执行内部优化,但在任意代理对象上调用时当然不能利用它们)。还请注意,
push
需要是通用的,才能在代理上工作,如果您尝试在键入的数组周围使用代理,它将是通用的。