【问题标题】:Array change listener [duplicate]数组更改侦听器 [重复]
【发布时间】:2012-11-29 08:10:46
【问题描述】:

可能重复:
Javascript - How to extend Array.prototype.push()?

如何通知(运行预定义函数)注册数组的任何更改(或至少添加或删除元素)? 我尝试使用原型。我不想因为没有提供我自己的一些代码示例而被责骂。所以这就是我希望喜欢使用它的方式。

var myArray = [];
myArray.bind(function() {
    console.log('wtf'); // Wed Thu Fri and what were you thinking?
});

我不需要矫枉过正。我基本上知道我将使用的 Array 函数作用域(push、pop、splice 和其他几个)。这是一种使用主干 MVC 的方法。我想在数组上运行逻辑,然后相应地突出显示视图。但是该视图已经附加到一个集合中。对该集合的任何更改都会重新呈现视图中的实际 DOM。我不想要那个。我只是想为 CSS 目的在视图中的相应 DOM 中添加或删除一个类。

【问题讨论】:

  • 如果你的环境中有 ES5,你可以使用一个对象,然后使用标准的 getter 和 setter
  • 它必须是一个数组,还是对象属性也可以工作?
  • 不知道你的最终目标是什么,但knockoutjs 确实处理得很好。

标签: javascript arrays listener extending


【解决方案1】:

这样的事情会设置数组 push() 的全局监控。

(function() {
  var _push = Array.prototype.push;
  Array.prototype.push = function() {
    console.log("push");
    return _push.apply(this, arguments);
  }
})();

否则,正如尼尔建议的那样,您可以创建另一个类。

var MonitoredArray = function() {
  var rv = [];
  var _push = rv.push;
  rv.push = function() {
    console.log("push()");
    console.log(arguments);
    return _push.apply(this, arguments);
  }
  return rv;
}

设置基本一次监控 N 个函数调用。

var MonitoredArray = function() {
  var rv = [];

  // the names of the functions we want to log:
  var logged_fns = ["push", "pop"];

  for (var i in logged_fns) { (function() {
    var name = logged_fns[i]
    var fn = rv[name];

    rv[name] = function() {
      console.log(name + "()");
      console.log(arguments);
      return fn.apply(rv, arguments);
    }
  })()}

  return rv;
}

类似的改编也应该适用于第一个示例。

【讨论】:

  • 有没有一种有效的方法可以将它应用到 Array 的所有函数中?或者我需要为每个人设置它吗?
  • @svidgen -- 您的 push 函数将其限制为仅接受 一个 变量,这与本机推送函数不同。
  • 添加了一个示例,该示例使用可变数量的参数“一次”执行多个覆盖。
  • @Neal,说得好。我将编辑前两个示例以使用 apply() 而不是 call()。
  • @AdrianBartholomew 即使将其应用于所有未涵盖的函数,也不会检测到简单的赋值 array[array.length]=...
【解决方案2】:

您正在寻找Object.observe,但它尚未广泛使用。在 Chrome Canary 中,启用 about:flags 上的“Experimental JavaScript”后,您可以尝试以下操作:

​var arr = [];

​Object.observe(arr, function(changes) {
    console.log("The array changed. Changes:", changes);
});

【讨论】:

  • 也许Array.observe 是更好的选择
  • 避免使用 Array.observe();因为它已经过时并且不再被许多浏览器支持。
  • 不推荐使用的选项
【解决方案3】:

我所做的是创建了自己的“数组”类型,它只是扩展了原型数组,然后我添加了自己的处理程序。

例如:

var MyArray = function() {
    var arr = [];
    arr.push = function() {
        console.log("PUSHING", arguments);
        return Array.prototype.push.apply(this, arguments);
    }

    return arr;
};

用法:

var arr = new MyArray;
arr.push(12, 3, 45);
...

小提琴:http://jsfiddle.net/maniator/vF659/

【讨论】:

  • 你能举个例子吗?我不是偷懒,老实说。我的困难在于,例如“推”,我不想替换它。我想在它结束时运行回调。
  • 我会推荐这种方法,因为覆盖主要的push 方法肯定会导致整个网站出现性能问题。
  • 这样吗? jsfiddle.net/vF659/3
  • @AdrianBartholomew 虽然如果您按照我的编辑中显示的“新”方法进行操作,您将能够通过执行new MyArray 毫无问题地重用MyArray
  • 它不会使用“新”。难道我做错了什么? jsfiddle.net/vF659/4
猜你喜欢
  • 2014-03-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-09-26
  • 2021-05-23
  • 1970-01-01
相关资源
最近更新 更多