我正在学习观察Array对象。我发现以下令人惊讶:
var fooArray = [];
Array.observe(fooArray, function(changes){
console.log('changes:', changes[0].type);
});
fooArray.push({});
导致更改类型为splice
而非add
哪种方法会导致add
类型的更改事件?在我看来,推动单一价值将是最可能的情况。
答案 0 :(得分:7)
MDN reference并不清楚触发每种更改类型的情况。这是一个详细的解释:
涵盖您希望在数组中发生的每个更改。以下所有功能都会触发它:
push()
pop()
shift()
unshift()
splice()
如果某个元素的值发生变化,则触发:
var arr = ['a', 'b', 'c'];
Array.observe(arr, function (changes) {
console.dir(changes);
});
arr[0] = 'A'; // triggers 'update'
值得一提的是,某些数组函数也可能会触发它,例如reverse()
。
由于看起来不直观,因此在向阵列添加/删除属性时会触发这些类型。例如:
var arr = ['a', 'b', 'c'];
Array.observe(arr, function (changes) {
console.dir(changes);
});
arr.foo = 'bar'; // triggers 'add'
delete arr.foo; // triggers 'delete'
P.S。:请参阅Jack's answer了解其行为的原因。
答案 1 :(得分:2)
变更观察者实际上是在Object
中实现的,Array
继承了var arr = [];
Object.observe(arr, function(changes) {
console.log(changes)
});
arr.push({});
。当您使用Object.observe()
时,您可以获得预期的行为:
[
{"type":"add","object":[{}],"name":"0"},
{"type":"update","object":[{}],"name":"length","oldValue":0}
]
输出:
Object.observe()
如你所见,这里发生了两件事:
Array.observe()
将这两个变更组合成一个拼接更改;基本上,任何影响数组长度的东西都属于这个范畴。 添加和删除更改类型仅针对普通属性触发,只留下更新更改类型以相同方式工作。
通过可选的第三个参数调整var arr = [];
Object.observe(arr, function(changes) {
console.log(changes)
}, ['add', 'update', 'delete', 'splice']);
arr.push({});
的接受类型列表,您可以确认:
[
{"type":"splice","object":[{}],"index":0,"removed":[],"addedCount":1}
]
输出:
Array.observe()
事实上,Array.observe = function(arr, callback) {
return Object.observe(arr, callback, ["add", "update", "delete", "splice"]);
};
可以像这样实现:
Array.observe()
因此,当您使用["reconfigure", "setPrototype", "preventExtensions"]
时,以下更改类型不会发送到您的回调:
{{1}}
答案 2 :(得分:1)
除了设置arr.b = 1
等自定义属性之外,至少目前在Node,Opera或Chrome中使用V8,还可以使用以下命令触发“添加”更改:
arr = []
arr[1] = 1 // "splice" change
arr[0] = 1 // "add" change