web-dev-qa-db-fra.com

Comment réparer Array indexOf () dans JavaScript pour les navigateurs Internet Explorer

Si vous avez déjà travaillé avec JavaScript, sachez qu'Internet Explorer n'implémente pas la fonction ECMAScript pour Array.prototype.indexOf () [y compris Internet Explorer 8]. Ce n'est pas un gros problème, car vous pouvez étendre les fonctionnalités de votre page avec le code suivant.

Array.prototype.indexOf = function(obj, start) {
     for (var i = (start || 0), j = this.length; i < j; i++) {
         if (this[i] === obj) { return i; }
     }
     return -1;
}

Quand devrais-je implémenter cela?

Devrais-je l'envelopper sur toutes mes pages avec la vérification suivante, qui vérifie si la fonction de prototype existe et, dans le cas contraire, continue et étend le prototype Array?

if (!Array.prototype.indexOf) {

    // Implement function here

}

Ou le navigateur vérifie-t-il et s'il s'agit d'Internet Explorer, alors mettez-le en œuvre?

//Pseudo-code

if (browser == IE Style Browser) {

     // Implement function here

}
294
Bobby Borszich

Fais-le comme ça...

if (!Array.prototype.indexOf) {

}

En tant que compatibilité recommandée par MDC .

En général, le code de détection du navigateur est un gros no-no.

213
Josh Stodola

Alternativement, vous pouvez utiliser le fonction jQuery 1.2 inArray , qui devrait fonctionner avec les navigateurs suivants:

jQuery.inArray( value, array [, fromIndex ] )
141
Moses Lee

Le code complet serait alors ceci:

if (!Array.prototype.indexOf) {
    Array.prototype.indexOf = function(obj, start) {
         for (var i = (start || 0), j = this.length; i < j; i++) {
             if (this[i] === obj) { return i; }
         }
         return -1;
    }
}

Pour une réponse et un code vraiment approfondis, ainsi que pour d’autres fonctions de tableau, consultez la question Stack Overflow Correction des fonctions de tableau JavaScript dans Internet Explorer (indexOf, forEach, etc.) = .

77
Luis Perez

La bibliothèque underscore.js a une fonction indexOf que vous pouvez utiliser à la place:

_.indexOf([1, 2, 3], 2)
16
scotta7exander

Vous devriez vérifier si ce n'est pas défini en utilisant if (!Array.prototype.indexOf).

De plus, votre implémentation de indexOf n’est pas correcte. Vous devez utiliser === au lieu de == dans votre instruction if (this[i] == obj), sinon [4,"5"].indexOf(5) serait égal à 1 selon votre implémentation, ce qui est incorrect.

Je vous recommande d'utiliser l'implémentation sur MDC .

10
Eli Grey

Il existe une solution officielle de Mozilla: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/indexOf

(function() {
    /**Array*/
    // Production steps of ECMA-262, Edition 5, 15.4.4.14
    // Reference: http://es5.github.io/#x15.4.4.14
    if (!Array.prototype.indexOf) {
        Array.prototype.indexOf = function(searchElement, fromIndex) {
            var k;
            // 1. Let O be the result of calling ToObject passing
            //    the this value as the argument.
            if (null === this || undefined === this) {
                throw new TypeError('"this" is null or not defined');
            }
            var O = Object(this);
            // 2. Let lenValue be the result of calling the Get
            //    internal method of O with the argument "length".
            // 3. Let len be ToUint32(lenValue).
            var len = O.length >>> 0;
            // 4. If len is 0, return -1.
            if (len === 0) {
                return -1;
            }
            // 5. If argument fromIndex was passed let n be
            //    ToInteger(fromIndex); else let n be 0.
            var n = +fromIndex || 0;
            if (Math.abs(n) === Infinity) {
                n = 0;
            }
            // 6. If n >= len, return -1.
            if (n >= len) {
                return -1;
            }
            // 7. If n >= 0, then Let k be n.
            // 8. Else, n<0, Let k be len - abs(n).
            //    If k is less than 0, then let k be 0.
            k = Math.max(n >= 0 ? n : len - Math.abs(n), 0);
            // 9. Repeat, while k < len
            while (k < len) {
                // a. Let Pk be ToString(k).
                //   This is implicit for LHS operands of the in operator
                // b. Let kPresent be the result of calling the
                //    HasProperty internal method of O with argument Pk.
                //   This step can be combined with c
                // c. If kPresent is true, then
                //    i.  Let elementK be the result of calling the Get
                //        internal method of O with the argument ToString(k).
                //   ii.  Let same be the result of applying the
                //        Strict Equality Comparison Algorithm to
                //        searchElement and elementK.
                //  iii.  If same is true, return k.
                if (k in O && O[k] === searchElement) {
                    return k;
                }
                k++;
            }
            return -1;
        };
    }
})();
9
Will V King

Je recommanderais ceci à tous ceux qui recherchent des fonctionnalités manquantes:

http://code.google.com/p/ddr-ecma5/

Il apporte la plupart des fonctionnalités manquantes d'ecma5 aux anciens navigateurs :)

5
Josh Mc

ça marche pour moi.

if (!Array.prototype.indexOf) {
  Array.prototype.indexOf = function(elt /*, from*/) {
    var len = this.length >>> 0;

    var from = Number(arguments[1]) || 0;
    from = (from < 0)? Math.ceil(from) : Math.floor(from);
    if (from < 0)
    from += len;

    for (; from < len; from++) {
      if (from in this && this[from] === elt)
        return from;
    }
    return -1;
  };
}
2
Allen Wong

C'était ma mise en œuvre. Essentiellement, ajoutez ceci avant tout autre script de la page. c'est-à-dire dans votre master pour une solution globale pour Internet Explorer 8. J'ai également ajouté la fonction de trim qui semble être utilisée dans de nombreux frameworks.

<!--[if lte IE 8]>
<script>
    if (!Array.prototype.indexOf) {
        Array.prototype.indexOf = function(obj, start) {
            for (var i = (start || 0), j = this.length; i < j; i++) {
                if (this[i] === obj) {
                    return i;
                }
            }
            return -1;
        };
    }

    if(typeof String.prototype.trim !== 'function') {
        String.prototype.trim = function() {
            return this.replace(/^\s+|\s+$/g, '');
        };
    };
</script>
<![endif]-->
2
Glennweb

Avec le Underscore.js

var arr=['a','a1','b'] _.filter(arr, function(a){ return a.indexOf('a') > -1; })

1
sri_bb