Javascript 将事件侦听器附加到 Push() 事件的数组

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/5306843/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 16:34:43  来源:igfitidea点击:

Attach Event Listener to Array for Push() Event

javascriptdom-events

提问by KingOfHypocrites

Is there a way to know when a user has pushed (via push()) an item onto an array?

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

Basically I have an asynchronous script that allows the user to push commands onto an array. Once my script loads, it execute the commands. The problems is, the user may push additional commands onto the array after my script has already run and I need to be notified when this happens. Keep in mind this is just a regular array that the user creates themselves. Google Analytics does something similar to this.

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

I also found this which is where I think Google does it, but I don't quite understand the code:

我还发现这是我认为谷歌这样做的地方,但我不太明白代码:

    Aa = function (k) {
        return Object.prototype[ha].call(Object(k)) == "[object Array]"

I also found a great example which seems to cover the bases, but I can't get my added push method to work correctly: http://jsbin.com/ixovi4/4/edit

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

回答by Qrt

You could use an 'eventify' function that overrides push in the passed array.

您可以使用“eventify”函数来覆盖传递的数组中的推送。

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

In the following example, 3 alerts should be raised as that is what the event handler (callback) does after eventify has been called.

在下面的示例中,应该引发 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);

回答by Jacob Relkin

The only sensible way to do this is to write a class that wraps around an array:

唯一明智的方法是编写一个环绕数组的类:

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'

回答by gotoweb

try this:

尝试这个:

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);

you can add functions at after pushing or before pushing

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

回答by gotoweb

Why not just do something like this?

为什么不做这样的事情呢?

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

Then define a handler.

然后定义一个处理程序。

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

Then use the eventPush in the place that you want a specific event to happen passing in the handler like so:

然后在您希望特定事件发生的地方使用 eventPush 传入处理程序,如下所示:

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

回答by shanks

I'd wrap the original array around a simple observer interface like so.

我会将原始数组包装在一个简单的观察者界面上,就像这样。

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));
}

Then i'd instantiate it with a base array

然后我会用一个基本数组实例化它

    //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

you can also extend the observer to observe other things like prePush or postPush or whatever events you'd like to emit as you interact with the internal base array.

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

回答by Westy92

Sometimes you need to queue things up before a callback is available. This solves that issue. Push any item(s) to an array. Once you want to start consuming these items, pass the array and a callback to QueuedCallback(). QueuedCallbackwill overload array.pushas your callback and then cycle through any queued up items. Continue to push items to that array and they will be forwarded directly to your callback. The array will remain empty.

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

Compatible with all browsers and IE 5.5+.

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

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

Sample usage here.

示例用法在这里

回答by Shadetheartist

This will add a function called onPushto all arrays, by default it shouldn't do anything so it doesn't interfere with normal functioning arrays.

这将添加一个调用onPush所有数组的函数,默认情况下它不应该做任何事情,所以它不会干扰正常运行的数组。

just override onPushon an individual array.

只需覆盖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');

This alerts 'somearray now has a swag in it'

这会提醒“somearray 现在有一个赃物”

回答by Bioukh

If you want to do it on a single array :

如果您想在单个数组上执行此操作:

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);)
};

回答by user2643083

for debugging purpose you can try. And track the calling function from the call stack.

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

yourArray.push = function(){debugger;}

回答by Grzesiek

A lot better way is to use the fact that those methods modify array length. The way to take advantage of that is quite simple (CoffeeScript):

更好的方法是利用这些方法修改数组长度的事实。利用它的方法非常简单(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
    })