如何扩展Array.prototype.push()?

时间:2009-02-21 07:52:06

标签: javascript arrays prototype

我正在尝试扩展Array.push方法,以便使用push将触发回调方法,然后执行正常的数组函数。

我不太确定如何做到这一点,但这里有一些我一直在玩的代码失败。

arr = [];
arr.push = function(data){

    //callback method goes here

    this = Array.push(data);
    return this.length;

}

arr.push('test');

7 个答案:

答案 0 :(得分:70)

由于push允许推送多个元素,因此我使用下面的arguments变量让真正的push方法具有所有参数。

此解决方案仅影响arr变量:

arr.push = function (){
    //Do what you want here...
    return Array.prototype.push.apply(this,arguments);
}

此解决方案会影响所有阵列。我不建议你这样做。

Array.prototype.push=(function(){
    var original = Array.prototype.push;
    return function() {
        //Do what you want here.
        return original.apply(this,arguments);
    };
})();

答案 1 :(得分:8)

首先你需要子类Array

ES6 :(目前不与Chrome50 +以外的babel或浏览器兼容https://kangax.github.io/compat-table/es6/

class SortedArray extends Array {
    constructor(...args) {
        super(...args);
    }
    push() {
        return super.push(arguments);
    }
}

es5 :( proto 几乎已被弃用,但它是目前唯一的解决方案)

function SortedArray() {
    var arr = [];
    arr.push.apply(arr, arguments);
    arr.__proto__ = SortedArray.prototype;
    return arr;
}
SortedArray.prototype = Object.create(Array.prototype);

SortedArray.prototype.push = function() {
    this.arr.push(arguments);
};

答案 2 :(得分:6)

Array.prototype.push是在JavaScript 1.2中引入的。它真的很简单:

Array.prototype.push = function() {
    for( var i = 0, l = arguments.length; i < l; i++ ) this[this.length] = arguments[i];
    return this.length;
};

你总是可以在前面添加一些内容。

答案 3 :(得分:5)

你可以这样做:

arr = []
arr.push = function(data) {
  alert(data); //callback

  return Array.prototype.push.call(this, data);
}

如果你处于没有通话的情况,你也可以选择这个解决方案:

arr.push = function(data) {
  alert(data); //callback

  //While unlikely, someone may be using psh to store something important
  //So we save it.
  var saved = this.psh;
  this.psh = Array.prototype.push;
  var ret = this.psh(data);
  this.psh = saved;
  return ret;
}

编辑:

虽然我告诉你如何做到这一点,但使用执行回调的不同方法然后只是调用数组上的推送而不是覆盖推送可能会更好。您最终可能会出现一些意想不到的副作用。例如,push似乎是varadic(采用可变数量的参数,比如printf),并且使用上面的内容会破坏它。

你需要弄乱_Arguments()和_ArgumentsLength()来正确覆盖这个函数。我强烈反对这条路线。

再次编辑: 或者你可以使用“参数”,这也是有效的。仍然建议不要走这条路。

答案 4 :(得分:1)

这个问题很古老,但是对于那些今天会发现这个问题的人来说,还有另一种更本地化的方法可以解决这个问题:Proxy

const target = [];

const handler = {
  set: function(array, index, value) {
    // call callback function here

    // The default behavior to store the value
    array[index] = value;

    // Indicate success
    return true;
  }
};

const proxyArray = new Proxy(target, handler);

答案 5 :(得分:0)

我想在对象被推送到数组之后调用一个函数,所以我做了以下事情:

myArray.push = function() { 
    Array.prototype.push.apply(this, arguments);
    myFunction();
    return myArray.length;
};

function myFunction() {
    for (var i = 0; i < myArray.length; i++) {
        //doSomething;
    }
}

答案 6 :(得分:-1)

我会这样做:

var callback = function() { alert("called"); };
var original = Array.prototype.push;
Array.prototype.push = function()
{
  callback();
  return original.apply(this, arguments);
};

如果你想让一个参数成为一个回调,你可以这样做:

var original = Array.prototype.push;
Array.prototype.push = function(callback)
{
  callback();
  return original.apply(this, Array.prototype.slice.call(arguments, 1));
}

这两项都已经过测试。