2009-02-21 18 views
24

Ich versuche, die Array.push-Methode zu erweitern, so dass mit Push eine Callback-Methode auslösen wird, dann führen Sie die normale Array-Funktion.So erweitern Sie Array.prototype.push()?

Ich bin nicht ganz sicher, wie das geht, aber hier ist ein Code, mit dem ich erfolglos gespielt habe.

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

    //callback method goes here 

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

} 

arr.push('test'); 

Antwort

62

Da Push erlaubt mehr als ein Element zu schieben, verwende ich die Argumente Variable unten, um die echte Push-Methode alle Argumente haben.

Diese Lösung betrifft nur die arr Variable:

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

Diese Lösung alle Arrays beeinflusst. Ich empfehle das nicht.

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

Meine bevorzugte Form des Wrappens von Funktionen besteht darin, Array.prototype.push zu übergeben, wenn Sie Ihre äußere Funktion ausführen und in der Funktion als die Variable original akzeptieren. Es ist ein wenig prägnanter – pottedmeat

+9

@pottedmeat: aber es ist weniger lesbar - erinnern Sie sich, Programme sind nicht nur für die Maschine geschrieben, sondern auch für andere Programmierer! – Christoph

+1

@some Vielen Dank für eine klare Erklärung des Prototyps und nicht! – Dorjan

4

Man könnte es auf diese Weise tun:

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

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

Wenn Sie in einer Situation ohne Aufruf sind, können Sie auch für diese Lösung gehen könnte:

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:

Während ich Ihnen sage, wie es geht, könnte es besser sein, wenn Sie eine andere Methode verwenden, die den Callback ausführt und dann nur pu aufruft Sh auf dem Array, anstatt zu übersteuern. Sie können mit einigen unerwarteten Nebenwirkungen enden. Zum Beispiel scheint push Varadic zu sein (nimmt eine variable Anzahl von Argumenten, wie printf), und die Verwendung der obigen würde das brechen.

Sie müssten mit _Arguments() und _ArgumentsLength() vorgehen, um diese Funktion ordnungsgemäß zu überschreiben. Ich schlage vor, diesen Weg zu gehen.

Noch einmal bearbeiten: Oder Sie könnten "Argumente" verwenden, das würde auch funktionieren. Trotzdem raten wir davon ab, diesen Weg zu gehen.

+0

Array.prototype.push.call (diese Daten); funktioniert nicht, da Array mehrere Elemente aufnehmen kann. Array.prototype.push.apply (dies, Argumente); – ToughPal

-1

Ich würde dies tun:

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

Wenn Sie ein Argument wollte ein Rückruf sein, könnten Sie dies tun:

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

Diese beiden getestet wurden.

+1

@cdmckay: Wenn du es getestet hättest, hättest du gemerkt, dass du eine Endlosschleife erstellt hast ... – some

+0

@some Mein Schlechter, schrieb ich das letzte Nacht. Ich habe sie repariert und getestet. – cdmckay

+1

@cdmckay: Jetzt funktioniert es, aber Sie verschmutzen den globalen Namespace mit 'original', und wenn eine andere Funktion den Wert von 'original' ändert, haben Sie das Array Push durchbrochen. Deine zweite Lösung macht keinen Sinn: Wenn ich beim Push-Vorgang den Rückruf liefern muss, kann ich den Rückruf selbst anrufen. – some

4

Array.prototype.push wurde in JavaScript 1.2 eingeführt. Es ist wirklich so einfach wie das:

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

Sie könnten immer etwas an der Vorderseite hinzufügen.

0

Ich wollte das Objekt eine Funktion nach rufen hat auf das Array geschoben worden ist, so habe ich die folgenden:

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

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

Zuerst müssen Sie Array Unterklasse:

ES6: (nicht kompatibel mit babel oder anderen Browser als Chrome50 + jetzt https://kangax.github.io/compat-table/es6/)

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

ES5 :(proto ist fast veraltet, aber es ist die einzige Lösung für jetzt) ​​

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

Neugierig, warum Sie eine Antwort auf eine Frage hinzufügen, die 7 Jahre alt ist. – Geuis

+1

Neugierig, warum jemand nicht? JS hat sich geändert. – pat

Verwandte Themen