Internet Explorer 上 Array.from 的替代或 polyfill [英] Alternative or polyfill for Array.from on the Internet Explorer

查看:25
本文介绍了Internet Explorer 上 Array.from 的替代或 polyfill的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在 Internet Explorer 上的 Angular 应用程序有问题.它可以在任何地方运行(Chrome、Mozilla、Edge)都没有问题,但可以在 IE 上运行.

I have a problem with my Angular App on the Internet Explorer. It runs everywhere without a problem (Chrome, Mozilla, Edge), but on on the IE.

我已经用开发者资源管理器分析了错误在哪里,它返回错误发生在以下行:

I have analyzed with the Developer Explorer where the error is and it returned that the error occurs on the following line:

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

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

Where this is the following error message I am getting:

对象不支持来自匿名函数的属性或方法......(等)

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

我在那里做的是我有一个名为 tmpSet() 包含以下数据:

What I am doing there is that I have a Set() named tmp which contains the following data:

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

Afterwards I am simply creating a simple array object from this Set.

我该如何解决这个问题?

How can I solve this problem?

编辑

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

Based on the recommendations I have added the following code to my App:

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

推荐答案

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

问题的原发帖人写道:

The first CORRECT answer here and for MDN

Original poster of question wrote:

我在那里做的是我有一个名为 tmp ...

What I am doing there is that I have a Set() named tmp ...

但是我们在这里已经有 3 个答案已经超过 4 年了,没有人Set 对象.
来自 MDN 的巨大 polyfill 没有使用 Set 对象!

But we have here 3 answers for already more than 4 years and nobody has tested it with a Set object.
The huge polyfill from MDN does not work with Set object!

它是从 MDN 复制并粘贴到已接受的答案中,未经测试.

It was copied from MDN and pasted into the accepted answer without testing.

我的 polyfill 解决方案也比来自 MDN 的不正确和巨大的 polyfill 短得多.

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

In the following solution you will find the explanation about the function(s) and their parameters in comments.

/**
 * @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 具有唯一值!例如:

Do not forget that a Set has unique values! For example:

//Only 11 version of IE and all modern browsers support Set.
var ar = [];
new Set('mama').forEach(function(v){ar.push(v)});
console.log(ar.join(',')); // 'm','a'

这篇关于Internet Explorer 上 Array.from 的替代或 polyfill的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆