2009-02-21 10 views
24

私はpushを使用してコールバックメソッドをトリガーし、通常の配列関数を実行するようにArray.pushメソッドを拡張しようとしています。Array.prototype.push()を拡張するには?

私はこれをどうやって行うのかは分かりませんが、ここではいくつかのコードを試してみましたが、失敗しました。あなたはそれをこのように行うことができます

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

    //callback method goes here 

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

} 

arr.push('test'); 

答えて

62

pushは複数の要素をプッシュすることができるので、実際のプッシュメソッドにすべての引数を持たせるために、以下のarguments変数を使用します。

このソリューションは、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); 
    }; 
})(); 
+0

私の好きな関数ラッピングの形式は、外部関数を実行するときにArray.prototype.pushを渡し、変数の元の関数として関数内で受け入れることです。それはもう少し簡潔です – pottedmeat

+9

@pottedmeat:しかし、それは読みにくいです - 覚えて、プログラムはマシンのためだけでなく、他のプログラマーのためにも書かれています! – Christoph

+1

@someプロトタイプをはっきりと説明してくれてありがとう! – Dorjan

4

:あなたはコールなしの状況にいる場合

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

は編集:

私はあなたにそれを行う方法を教えていますが、あなたはコールバックを実行してからpuを呼び出す別のメソッドpushをオーバーライドするのではなく、配列にshを書きます。予期しない副作用が生じることがあります。例えば、pushはvaradic(printfのような可変数の引数をとります)と思われ、上記を使用するとそれが破られます。

この関数を適切にオーバーライドするには、_Arguments()と_ArgumentsLength()を混乱させる必要があります。私はこのルートに対して強く勧めます。

もう一度編集: 「引数」を使用することもできますが、それも機能します。しかし、このルートを取ることに反対してください。

+0

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); }; 
Array.prototype.push.call(この、データ)です。 Arrayは複数の項目を取ることができるため、動作しません。 Array.prototype.push.apply(this、arguments); – ToughPal

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

これらの両方がテストされています。

+1

@cdmckay:もしあなたがそれをテストしたなら、あなたは無限ループが作成されていることに気づいたでしょう。 – some

+0

@some私の悪い、私は最後の夜遅くそれを書きました。私はそれらを修正してテストしました。 – cdmckay

+1

@cdmckay:これでうまくいきましたが、グローバル名前空間を 'original'で汚染し、他の関数が 'original'の値を変更すると、配列プッシュが壊れてしまいました。あなたの2番目の解決策は意味をなさない:私が押してコールバックを供給する必要がある場合、私はコールバックを自分で呼び出すことができます。 – some

4

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

いつもその前に何かを追加することができます。

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

まずはArrayをサブクラス必要があります。

ES6:(互換性がありませんバベルまたはChrome50 +以外のブラウザで今https://kangax.github.io/compat-table/es6/

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

ES5 :(プロトほぼ非推奨が、それは今のところ唯一の解決策)

+0

7歳以上の質問に答えを追加している理由が不思議です。 – Geuis

+1

好奇心をそそる誰かがなぜですか? JSが変更されました。 – pat

関連する問題