Internet Explorer上的Array.from

时间:2016-04-23 12:40:11

标签: javascript arrays angularjs internet-explorer

我在Internet Explorer上的角度应用程序出了问题。它运行无处不在(Chrome,Mozilla,Edge),但在IE上。

我已经在Developer Explorer中分析了错误,并且返回错误发生在以下行:

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

这是我收到的以下错误消息:

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

我在做的是,我有一个名为Set()的{​​{1}},其中包含以下数据:

enter image description here

之后我只是从这个tmp创建一个简单的数组对象。

我该如何解决这个问题?

修改

根据建议,我已将以下代码添加到我的应用中:

Set

5 个答案:

答案 0 :(得分:40)

以下文档模式不支持

Array.from:Quirks,Internet Explorer 6标准,Internet Explorer 7标准,Internet Explorer 8标准,Internet Explorer 9标准,Internet Explorer 10标准,Internet Explorer 11标准。 Windows 8.1不支持。

只需将以下代码添加到您的网页(JS code was copied from developer.mozilla.org)即可。它将模拟ES6的Array.from方法。

  

Array.from被添加到第6版的ECMA-262标准中;如   这样它可能不存在于标准的其他实现中。   您可以通过在以下位置插入以下代码来解决此问题   脚本的开头,允许使用Array.from   本机不支持它的实现。这个算法是   正好是ECMA-262第6版中指定的那个,假设是Object   和TypeError有它们的原始值和callback.call   计算为Function.prototype.call的原始值。在   另外,由于真正的iterables不能被polyfilled,这个   实现不支持在中定义的泛型迭代   第6版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;
    };
  }());
}

答案 1 :(得分:6)

我遇到了同样的问题。看着polyfill,它威胁巨大。这是2行短解决方案。

OP基本上需要从类似数组的对象创建简单数组。我习惯了我最有效的2行普通for循环(我不得不从HTML DOM节点列表数组对象创建数组,同样适用于JavaScript arguments对象)。

对于OP的情况,听起来可能就是这样:

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.

使其成为单独的功能,并为IE&lt; 9案例提供3行通用可重用解决方案。

以下是单独函数的外观:

/**
 * @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:以下是forEach callback的相关说明,了解如何使用customEach回调。

答案 2 :(得分:4)

虽然IE不支持,但您可以使用MDN的polyfill

答案 3 :(得分:1)

此处和MDN的第一个正确答案

问题的原始发帖人写道:

我正在做的是,我有一个名为Set()的{​​{1}} ...

但是我们这里已经有4年多的3个答案了,没人已经用 Set 对象对其进行了测试。
huge polyfill from MDN不适用于tmp对象!

它是从MDN复制而来的,未经测试就粘贴到了可接受的答案中。

我的polyfill解决方案也比来自MDN的不正确且庞大的polyfill短得多。

在以下解决方案中,您将在注释中找到有关功能及其参数的说明。

Set
/**
 * @param "arr" (required) - array-like or iterable object to convert it to an array.
 * @param "callbackFn" (optional) - function to call on every element of the array.
 * @param "thisArg" (optional) - value to use as this when executing callback
 * Return value - new Array instance
 *
 * The callbackFn argument usage is like in Array.map() callback.
 * The callbackFn function accepts the following arguments:
 *      @param "currentValue" (required) - the current element being processed in the array.
 *      @param "index" (optional) - the index of the current element being processed in the array.
 *      @param "array" (optional) - he array map was called upon.
 * Callback function that is called for every element of "arr". Each time callback executes, the returned value is added to new array ("arNew").
 */
function arrayFrom(arr, callbackFn, thisArg)
{
    //if you need you can uncomment the following line
    //if(!arr || typeof arr == 'function')throw new Error('This function requires an array-like object - not null, undefined or a function');

    var arNew = [],
        k = [], // used for convert Set to an Array
        i = 0;

    //if you do not need a Set object support then
    //you can comment or delete the following if statement
    if(window.Set && arr instanceof Set)
    {
        //we use forEach from Set object
        arr.forEach(function(v){k.push(v)});
        arr = k
    }

    for(; i < arr.length; i++)
        arNew[i] = callbackFn
            ? callbackFn.call(thisArg, arr[i], i, arr)
            : arr[i];

    return arNew
}

//You could also use it without the following line, but it is not recommended because native function is faster.
Array.from = Array.from || arrayFrom; //We set it as polyfill

//HOW TO USE IT:

function myCallback1(x){return x+x}

function myCallback2(o){return o.innerHTML}

var str = 'Super!',
    array = str.split(''),//['S','u','p','e','r','!']
    arrayLike1 = window.Set ? new Set(str) : array, //array for IE < 10. Only 11 version of IE supports Set.
    arrayLike2 = document.querySelectorAll('b');//NodeList
    arrayLike3 = document.getElementsByTagName('b');//HTMLCollection

console.log(arrayFrom(str).join(','));//S,u,p,e,r,!
console.log(arrayFrom(array).join(','));//S,u,p,e,r,!
console.log(arrayFrom(str, myCallback1).join(','));//SS,uu,pp,ee,rr,!!
console.log(arrayFrom(arrayLike1, myCallback1).join(','));//SS,uu,pp,ee,rr,!!
console.log(arrayFrom(arrayLike2, myCallback2).join(','));//aaa,bbb
console.log(arrayFrom(arrayLike3, myCallback2).join(','));//aaa,bbb
//You can also use it as polyfill:
console.log(Array.from(str).join(','));//S,u,p,e,r,!

不要忘记<b>aaa</b> <b>bbb</b>具有唯一的值!例如:

Set

答案 4 :(得分:0)

您可以将slice.call用于类似数组的对象。这意味着您的代码将显示为:

myDataSet[index - 1].data = [].slice.call(tmp);