Как расширить Array.prototype.push ()? - PullRequest
28 голосов
/ 21 февраля 2009

Я пытаюсь расширить метод Array.push, чтобы использование push вызывало метод обратного вызова, а затем выполняло обычную функцию массива.

Я не совсем уверен, как это сделать, но вот код, с которым я безуспешно играл.

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

    //callback method goes here

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

}

arr.push('test');

Ответы [ 6 ]

70 голосов
/ 21 февраля 2009

Поскольку 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);
    };
})();
8 голосов
/ 10 октября 2016

Сначала вам нужен подкласс Array:

ES6: (сейчас не совместимо с babel или браузером, кроме Chrome50 + 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);
};
6 голосов
/ 03 апреля 2009

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

Вы всегда можете добавить что-то перед этим.

5 голосов
/ 21 февраля 2009

Вы можете сделать это так:

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

Edit:

В то время как я говорю вам, как это сделать, вам лучше использовать другой метод, который выполняет обратный вызов, а не просто переопределяет push-вызов массива. Вы можете получить неожиданные побочные эффекты. Например, push выглядит как случайный (принимает переменное количество аргументов, например printf), и использование вышеперечисленного могло бы его сломать.

Вам нужно было бы возиться с _Arguments () и _ArgumentsLength (), чтобы правильно переопределить эту функцию. Я настоятельно рекомендую против этого маршрута.

Редактировать еще раз: Или вы могли бы использовать «аргументы», это тоже сработало бы. Тем не менее, советую не идти по этому маршруту.

0 голосов
/ 21 февраля 2015

Я хотел вызвать функцию после объект был помещен в массив, поэтому я сделал следующее:

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

function myFunction() {
    for (var i = 0; i < myArray.length; i++) {
        //doSomething;
    }
}
0 голосов
/ 21 февраля 2009

Я бы сделал это:

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

Они оба были проверены.

...