0

配列のようなオブジェクトがあります。これは、数値プロパティ ( 012...) とプロパティがあることを意味しlengthます。

そのプロトタイプでは、次のように、それをクリアするメソッドを宣言します。

'clear': function() {
    Array.prototype.splice.call(this, 0, this.length);
    return this;
}

これは、ほとんどのブラウザーで期待どおりに機能しますが、Internet Explorer では機能しません。

完全に有効な配列のようなオブジェクトを取得します。

var arrayLike = {
    length: 3,
    '0': 'a',
    '1': 'b',
    '2': 'c'
};

そしてそれを明確につなぎ合わせます:

Array.prototype.splice.call(arrayLike, 0, arrayLike.length);

標準準拠のブラウザーでは、これは正しい結果です。

arrayLike.length ==     0    ;
arrayLike[0]     == undefined;
arrayLike[1]     == undefined;
arrayLike[2]     == undefined;

しかし、IE 8 では、次のようになります。

arrayLike.length ==  0 ; // (!!)
arrayLike[0]     == 'a';
arrayLike[1]     == 'b';
arrayLike[2]     == 'c';

はい、それは機能するかどうかに関係なく、必要なだけ機能します。

Array.prototype.splice.call今、配列のようなオブジェクトをネイティブにクリアする唯一の方法だと思います。おそらく、IE8 の場合は条件付きでプライベート コピーにポリフィルすることができます (他のブラウザーでは 1 回だけパフォーマンス ヒットが発生しますが、1 回だけです)。

それとも、オブジェクトをクリアする別の方法がありますか? それもIE8でネイティブ?私が見ていないものはありますか?

Ps: IE8 で実行するためのJsFiddle 。

4

3 に答える 3

1

IEがめちゃめちゃ… 配列オブジェクトを拡張しても、IEはスプライスをめちゃくちゃにするようです。以下の私のテストを参照してください。

// create an object constructor
var arrayLike = function() {
    this.clear = function() {
        this.splice( 0, this.length );
    };
};
// use prototypical inheritance to inherit array functionality
arrayLike.prototype = [];
arrayLike.constructor = arrayLike;

// testing clear method fails...
var arrayLikeObject = new arrayLike();
arrayLikeObject.push( 'foo' );
console.log( arrayLikeObject[ 0 ] ); // outputs foo
arrayLikeObject.clear();
console.log( arrayLikeObject[ 0 ] ); // outputs foo

// yet the same method works on a normal array
var test = [];
test.push( 'foo2' );
test.splice( 0, test.length );
console.log( test[0] ); // outputs undefined

なんてこったIE...

于 2012-10-01T23:54:44.510 に答える
0

男、これは面白い。IE8では非常に奇妙な方法Array.prototype.spliceで壊れています。

私はあなたにこれを示さなければなりません(あなたが望むならそれをスキップしてください、以下の解決策)。

ご覧のとおり、これはIEの「a」に警告しますね。

// Create an array-like object.
var arrayLike = {
    length: 1,
    '0': 'a'
};

// Clean it with splice. This should work in ES5.
Array.prototype.splice.call(arrayLike, 0, 2);

// Note that IE does set the length to zero. We need to check an item.
alert(arrayLike[0]);

jsfiddle

では、無効な長さに設定するとどうなりますか?特にこの効果の場合、「3」(「2」はIE8でも同じ結果になります)。

さて、 IE8でこのアラートは何ですか?

var arrayLike = {
    length: 3,      // <--
    '0': 'a'
};

Array.prototype.splice.call(arrayLike, 0, 2);

alert(arrayLike[0]);

jsfiddle

いずれにせよ、私はその奇妙な働き方に頼るつもりはありません。私は本番環境でひどく奇妙なバグを抱えたくありません。これはあなたがそれを修正する方法です:

まず、コードをIIFEでラップしていますか?あなたがすべき。次に、のプライベートコピーがあることを確認しますArray.prototype.splice。私はIIFEの冒頭でこれらのことを宣言します。

// Call it whatever you want.
var protoSplice = Array.prototype.splice;

次に、いくつかの初期化メソッドで(または、いつでも使用する前に、それが使用されていることを確認してください)、polyfillメソッドを呼び出します。

polyfill();

これはテストと修正を呼び出します。

function polyfill() {
    // ...
    genericSpliceWorks() || fixGenericSplice();
    // ...
}

使用する方法は次のとおりです。

function genericSpliceWorks() {

    // Create an array-like object.
    var arrayLike = {
    length: 1,
    '0': true
    };

    // Clean it with splice. This should work in ES5.
    protoSplice.call(arrayLike, 0, 2);

    // Note that IE does set the length to 0. We need to check an item.
    return !arrayLike[0];

}

function fixGenericSplice() {

    // Re-set our local protoSplice variable to something that works.
    // Note: this implementation only works with the first two arguments
    // of splice. This means that it does not add extra elements to the
    // array. It's as much as I need.
    protoSplice = function(index, count) {

        // If count is more than zero, run until it's zero, decrementing
        // each time.
        while (count--) {

            // Remove an array item from index, while incrementing index
            // for the next time.
            delete this[index++];

            // Decrement the length.
            this.length--;

        }

    };

}

タダ!今は動作します:)

于 2012-10-02T20:07:10.667 に答える
0

私の直感Array.prototype.splice.callでは、Array. 私には、それはハックに思えます。

はい、おそらくほとんどのブラウザーで動作しますが、あるプロトタイプ用に設計された操作を、そのプロトタイプではないオブジェクトに対して実行しようとしています。私は IE のファンではありませんが、IE はハッカーのように見えます。

私の2¢は、プロトタイプとして使用して新しい「Array-like」オブジェクトを作成することArrayです。例:

var ArrayLike = function(){
    this.push.apply(this, arguments);
};
ArrayLike.prototype = Array.prototype;
ArrayLike.constructor = function(){};
ArrayLike.prototype.clear = function(){
    // Array.prototype.splice.call(this, 0, this.length);
    this.splice(0, this.length); // all of Array's methods are available to ArrayLike
    return this;
}

var arrayLike = new ArrayLike('a', 'b', 'c');
console.log(arrayLike.length);  // 3
arrayLike.clear();              // clear
console.log(arrayLike.length);  // 0

...または独自のメソッドを記述します。

于 2012-10-01T21:23:14.263 に答える