在什么条件下Array.observe的“添加”事件会触发?

时间:2015-03-26 00:30:22

标签: javascript arrays

我正在学习观察Array对象。我发现以下令人惊讶:

var fooArray = [];
Array.observe(fooArray, function(changes){
    console.log('changes:', changes[0].type);
});
fooArray.push({});

导致更改类型为splice而非add

哪种方法会导致add类型的更改事件?在我看来,推动单一价值将是最可能的情况。

3 个答案:

答案 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()

如你所见,这里发生了两件事:

  1. 在属性0(即第一个元素)
  2. 下添加对象
  3. 更新length属性以反映新元素数。
  4. 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