Javascript:将事件侦听器附加到Array以进行Push()事件

时间:2011-03-15 02:25:17

标签: javascript javascript-events

有没有办法知道用户何时(通过push())将项目推送到数组?

基本上我有一个异步脚本,允许用户将命令推送到数组上。加载脚本后,它会执行命令。问题是,用户可能会在我的脚本运行后将其他命令推送到阵列上,我需要在发生这种情况时收到通知。请记住,这只是用户自己创建的常规数组。 Google Analytics(分析)会做与此类似的事情。

我也发现这是我认为谷歌所做的,但我不太了解代码:Aa = function(k){             return Object.prototype [ha] .call(Object(k))==“[object Array]”

我还找到了一个很好的例子,似乎涵盖了基础,但我无法让我添加的推送方法正常工作: http://jsbin.com/ixovi4/4/edit

11 个答案:

答案 0 :(得分:24)

你可以使用' eventify'覆盖推送传递数组的函数。

var eventify = function(arr, callback) {
    arr.push = function(e) {
        Array.prototype.push.call(arr, e);
        callback(arr);
    };
};

在下面的示例中,应该引发3个警报,因为这是事件处理程序(回调)在调用eventify之后所做的事情。

var testArr = [1, 2];

testArr.push(3);

eventify(testArr, function(updatedArr) {
  alert(updatedArr.length);
});

testArr.push(4);
testArr.push(5);
testArr.push(6);

答案 1 :(得分:22)

唯一明智的做法是编写一个包装数组的类:

function EventedArray(handler) {
   this.stack = [];
   this.mutationHandler = handler || function() {};
   this.setHandler = function(f) {
      this.mutationHandler = f;
   };
   this.callHandler = function() { 
      if(typeof this.mutationHandler === 'function') {
         this.mutationHandler();
      }
   };
   this.push = function(obj) {
      this.stack.push(obj);
      this.callHandler();
   };
   this.pop = function() {
      this.callHandler();
      return this.stack.pop();
   };
   this.getArray = function() {
      return this.stack;
   }
}

var handler = function() {
   console.log('something changed');
};

var arr = new EventedArray(handler);

//or 

var arr = new EventedArray();
arr.setHandler(handler);


arr.push('something interesting'); //logs 'something changed'

答案 2 :(得分:13)

试试这个:

var MyArray = function() { };
MyArray.prototype = Array.prototype;
MyArray.prototype.push = function() {
    console.log('push now!');
    for(var i = 0; i < arguments.length; i++ ) {
        Array.prototype.push.call(this, arguments[i]);
    }
};

var arr = new MyArray();
arr.push(2,3,'test',1);

您可以在推后或推送之前添加功能

答案 3 :(得分:3)

为什么不做这样的事情?

Array.prototype.eventPush = function(item, callback) {
  this.push(item);
  callback(this);
}

然后定义一个处理程序。

handler = function(array) {
    console.log(array.length)
}

然后在希望特定事件发生的地方使用eventPush,如下所示:

a = []
a.eventPush(1, handler);
a.eventPush(2, handler);

答案 4 :(得分:2)

我将原始数组包装在一个简单的观察者界面周围。

function EventedList(list){
    this.listbase = list;
    this.events = [];
}

EventedList.prototype.on = function(name, callback){
    this.events.push({
        name:name,
        callback:callback
    });
}

//push to listbase and emit added event
EventedList.prototype.push = function(item){
    this.listbase.push(item);
    this._emit("added", item)
}

EventedList.prototype._emit = function(evtName, data){
    this.events.forEach(function(event){
        if(evtName === event.name){
            event.callback.call(null, data, this.listbase);
        }
    }.bind(this));
}

然后我用基数组

实例化它
    //returns an object interface that lets you observe the array
    var evtList = new EventedList([]);

    //attach a listener to the added event
    evtList.on('added', function(item, list){
         console.log("added event called: item = "+ item +", baseArray = "+ list);
    })

    evtList.push(1) //added event called: item = 1, baseArray = 1
    evtList.push(2) //added event called: item = 2, baseArray = 1,2
    evtList.push(3) //added event called: item = 3, baseArray = 1,2,3

您还可以扩展观察者以观察其他内容,例如prePush或postPush,或者当您与内部基本阵列交互时要发出的任何事件。

答案 5 :(得分:1)

这将为所有数组添加一个名为onPush的函数,默认情况下它不应该执行任何操作,因此它不会干扰正常运行的数组。

只需覆盖单个数组上的onPush

Array.prototype.oldPush = Array.prototype.push;
Array.prototype.push = function(obj){
    this.onPush(obj);
    this.oldPush(obj);
};
//Override this method, be default this shouldnt do anything. As an example it will.
Array.prototype.onPush = function(obj){
    alert(obj + 'got pushed');
};

//Example
var someArray = [];

//Overriding
someArray.onPush = function(obj){
    alert('somearray now has a ' + obj + ' in it');
};

//Testing
someArray.push('swag');

此警告&#39; somearray现在有一个蠢货&#39;

答案 6 :(得分:1)

有时您需要在回调可用之前排队。这解决了这个问题。将任何项目推送到数组。一旦您想开始使用这些项目,请将数组和回调传递给QueuedCallback()QueuedCallback将重载array.push作为您的回调,然后循环浏览任何排队的项目。继续将项目推送到该阵列,它们将直接转发到您的回调。该数组将保持为空。

兼容所有浏览器和IE 5.5 +。

var QueuedCallback = function(arr, callback) {
  arr.push = callback;
  while (arr.length) callback(arr.shift());
};

示例用法here

答案 7 :(得分:0)

未经测试,但我假设这样的事情可行:

Array.prototype.push = function(e) {
    this.push(e);
    callbackFunction(e);
}

答案 8 :(得分:0)

更好的方法是使用这些方法修改数组长度的事实。 利用它的方法非常简单(CoffeeScript):

class app.ArrayModelWrapper extends Array
  constructor: (arr,chName,path)->
    vl  = arr.length
    @.push.apply(@,arr)
    Object.defineProperty(@,"length",{
      get: ->vl
      set: (newValue)=>
        console.log("Hello there ;)")
        vl = newValue
        vl
      enumerable: false
    })

答案 9 :(得分:0)

如果你想在一个阵列上这样做:

var a = [];

a.push = function(item) {
    Array.prototype.push.call(this, item);
    this.onPush(item);
};

a.onPush = function(obj) {
    // Do your stuff here (ex: alert(this.length);)
};

答案 10 :(得分:0)

出于调试目的,您可以尝试。并从调用堆栈中跟踪调用函数。

yourArray.push = function(){debugger;}