web-dev-qa-db-fra.com

Array.from sur Internet Explorer

J'ai un problème avec mon angular sur Internet Explorer. Elle fonctionne partout sans problème (Chrome, Mozilla, Edge), mais sur IE).

J'ai analysé avec l'explorateur de développeur où se trouve l'erreur et il est retourné que l'erreur se produit sur la ligne suivante:

myDataSet[index - 1].data = Array.from(tmp);

Où ceci est le message d'erreur suivant que j'obtiens:

Object does not support property or method from at Anonymous function....(etc.)

Ce que je fais là, c'est que j'ai une Set() nommée tmp qui contient les données suivantes:

enter image description here

Ensuite, je crée simplement un objet tableau simple à partir de ce Set.

Comment puis-je résoudre ce problème?

[~ # ~] modifier [~ # ~]

Sur la base des recommandations, j'ai ajouté le code suivant à mon application:

if (!Array.from) {
  Array.from = (function () {
    var toStr = Object.prototype.toString;
    var isCallable = function (fn) {
      return typeof fn === 'function' || toStr.call(fn) === '[object Function]';
    };
    var toInteger = function (value) {
      var number = Number(value);
      if (isNaN(number)) { return 0; }
      if (number === 0 || !isFinite(number)) { return number; }
      return (number > 0 ? 1 : -1) * Math.floor(Math.abs(number));
    };
    var maxSafeInteger = Math.pow(2, 53) - 1;
    var toLength = function (value) {
      var len = toInteger(value);
      return Math.min(Math.max(len, 0), maxSafeInteger);
    };

    // The length property of the from method is 1.
    return function from(arrayLike/*, mapFn, thisArg */) {
      // 1. Let C be the this value.
      var C = this;

      // 2. Let items be ToObject(arrayLike).
      var items = Object(arrayLike);

      // 3. ReturnIfAbrupt(items).
      if (arrayLike == null) {
        throw new TypeError("Array.from requires an array-like object - not null or undefined");
      }

      // 4. If mapfn is undefined, then let mapping be false.
      var mapFn = arguments.length > 1 ? arguments[1] : void undefined;
      var T;
      if (typeof mapFn !== 'undefined') {
        // 5. else
        // 5. a If IsCallable(mapfn) is false, throw a TypeError exception.
        if (!isCallable(mapFn)) {
          throw new TypeError('Array.from: when provided, the second argument must be a function');
        }

        // 5. b. If thisArg was supplied, let T be thisArg; else let T be undefined.
        if (arguments.length > 2) {
          T = arguments[2];
        }
      }

      // 10. Let lenValue be Get(items, "length").
      // 11. Let len be ToLength(lenValue).
      var len = toLength(items.length);

      // 13. If IsConstructor(C) is true, then
      // 13. a. Let A be the result of calling the [[Construct]] internal method of C with an argument list containing the single item len.
      // 14. a. Else, Let A be ArrayCreate(len).
      var A = isCallable(C) ? Object(new C(len)) : new Array(len);

      // 16. Let k be 0.
      var k = 0;
      // 17. Repeat, while k < len… (also steps a - h)
      var kValue;
      while (k < len) {
        kValue = items[k];
        if (mapFn) {
          A[k] = typeof T === 'undefined' ? mapFn(kValue, k) : mapFn.call(T, kValue, k);
        } else {
          A[k] = kValue;
        }
        k += 1;
      }
      // 18. Let putStatus be Put(A, "length", len, true).
      A.length = len;
      // 20. Return A.
      return A;
    };
  }());
}
28
Robert J.

Array.from Non pris en charge dans les modes de document suivants: bizarreries, normes Internet Explorer 6, normes Internet Explorer 7, normes Internet Explorer 8, normes Internet Explorer 9, normes Internet Explorer 10, normes Internet Explorer 11. Non pris en charge dans Windows 8.1.

Ajoutez simplement le code ci-dessous à votre page ( le code JS a été copié depuis developer.mozilla.org ). Il émulera la méthode Array.from D'un ES6.

Array.from a été ajouté à la norme ECMA-262 dans la 6e édition; en tant que tel, il peut ne pas être présent dans d'autres implémentations de la norme. Vous pouvez contourner ce problème en insérant le code suivant au début de vos scripts, ce qui permet d'utiliser Array.from dans les implémentations qui ne le prennent pas nativement en charge. Cet algorithme est exactement celui spécifié dans ECMA-262, 6e édition, en supposant que Object et TypeError ont leurs valeurs d'origine et que callback.call est évalué à la valeur d'origine de Function.prototype.call. De plus, comme les vrais itérables ne peuvent pas être remplis de manière polyvalente, cette implémentation ne prend pas en charge les itérables génériques tels que définis dans la 6e édition d'ECMA-262.

if (!Array.from) {
  Array.from = (function () {
    var toStr = Object.prototype.toString;
    var isCallable = function (fn) {
      return typeof fn === 'function' || toStr.call(fn) === '[object Function]';
    };
    var toInteger = function (value) {
      var number = Number(value);
      if (isNaN(number)) { return 0; }
      if (number === 0 || !isFinite(number)) { return number; }
      return (number > 0 ? 1 : -1) * Math.floor(Math.abs(number));
    };
    var maxSafeInteger = Math.pow(2, 53) - 1;
    var toLength = function (value) {
      var len = toInteger(value);
      return Math.min(Math.max(len, 0), maxSafeInteger);
    };

    // The length property of the from method is 1.
    return function from(arrayLike/*, mapFn, thisArg */) {
      // 1. Let C be the this value.
      var C = this;

      // 2. Let items be ToObject(arrayLike).
      var items = Object(arrayLike);

      // 3. ReturnIfAbrupt(items).
      if (arrayLike == null) {
        throw new TypeError("Array.from requires an array-like object - not null or undefined");
      }

      // 4. If mapfn is undefined, then let mapping be false.
      var mapFn = arguments.length > 1 ? arguments[1] : void undefined;
      var T;
      if (typeof mapFn !== 'undefined') {
        // 5. else
        // 5. a If IsCallable(mapfn) is false, throw a TypeError exception.
        if (!isCallable(mapFn)) {
          throw new TypeError('Array.from: when provided, the second argument must be a function');
        }

        // 5. b. If thisArg was supplied, let T be thisArg; else let T be undefined.
        if (arguments.length > 2) {
          T = arguments[2];
        }
      }

      // 10. Let lenValue be Get(items, "length").
      // 11. Let len be ToLength(lenValue).
      var len = toLength(items.length);

      // 13. If IsConstructor(C) is true, then
      // 13. a. Let A be the result of calling the [[Construct]] internal method of C with an argument list containing the single item len.
      // 14. a. Else, Let A be ArrayCreate(len).
      var A = isCallable(C) ? Object(new C(len)) : new Array(len);

      // 16. Let k be 0.
      var k = 0;
      // 17. Repeat, while k < len… (also steps a - h)
      var kValue;
      while (k < len) {
        kValue = items[k];
        if (mapFn) {
          A[k] = typeof T === 'undefined' ? mapFn(kValue, k) : mapFn.call(T, kValue, k);
        } else {
          A[k] = kValue;
        }
        k += 1;
      }
      // 18. Let putStatus be Put(A, "length", len, true).
      A.length = len;
      // 20. Return A.
      return A;
    };
  }());
}
44
Ali Mamedov

J'ai fait face au même problème. Vu le polyfill et il menace énorme. Voici une solution courte de 2 lignes.

L'OP doit essentiellement créer un tableau simple à partir de son objet semblable à un tableau. J'ai utilisé à mon goût la boucle simple for 2 lignes la plus efficace (j'ai dû créer un tableau à partir d'un objet ressemblant à un tableau de liste de nœuds HTML DOM, de même pour JavaScript arguments objet).

Pour le cas de l'OP, cela pourrait ressembler à ceci:

var temp_array = [],
    length = tmp.length;

for (var i = 0; i < length; i++) {
    temp_array.Push(tmp[i]);
}

// Here you get the normal array "temp_array" containing all items
// from your `tmp` Set.

Faites-en une fonction séparée et vous obtenez une solution réutilisable universelle de 3 lignes pour le cas IE <9.

Voici à quoi peut ressembler la fonction séparée:

/**
 * @param arr The array | array-like data structure.
 * @param callback The function to process each element in the 'arr'.
 * The callback signature and usage is assumed similar to the 
 * native JS 'forEach' callback argument usage.
 */
function customEach(arr, callback) {
    'use strict';
    var l = arr.length;
    for (var i = 0; i < l; i++) {
        callback(arr[i], i, arr);
    }
};

PS: voici la description pertinente de forEach callback pour voir comment utiliser le callback customEach.

7
bob-12345

Bien qu'il ne soit pas pris en charge sur C'EST-À-DIRE , vous pouvez utiliser le polyfill de MDN.

5
Nina Scholz