Alternative or Polyfill for Array.From on the Internet Explorer

Alternative or polyfill for Array.from on the Internet Explorer

The first CORRECT answer here and for MDN

Original poster of question wrote:

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

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!

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

My polyfill solution is also much shorter than incorrect and huge polyfill from MDN.

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>

IE 11 does not support method ‘from’

The Array​.from method does not work at all in IE. Check the MDN page for compatibility.

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/from#Browser_compatibility

You can use the polyfill to make it work:

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/from#Polyfill

From the documentation:

Array.from was added to the ECMA-262 standard in the 6th edition (ES2015); as such it may not be present in other implementations of the standard. You can work around this by inserting the following code at the beginning of your scripts, allowing use of Array.from in implementations that don't natively support it. This algorithm is exactly the one specified in ECMA-262, 6th edition, assuming Object and TypeError have their original values and that callback.call evaluates to the original value of Function.prototype.call. In addition, since true iterables can not be polyfilled, this implementation does not support generic iterables as defined in the 6th edition of ECMA-262.

Here is the suggested polyfill from the documentation:

// Production steps of ECMA-262, Edition 6, 22.1.2.1if (!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; }; }());}

Javascript - What is alternative to find function?

A polyfill is a code that provides the functionality that you normally expect the browser to provide you natively. Here is the polyfill for Array.find

if (!Array.prototype.find) {
Array.prototype.find = function(predicate) {
if (this === null) {
throw new TypeError('Array.prototype.find called on null or undefined');
}
if (typeof predicate !== 'function') {
throw new TypeError('predicate must be a function');
}
var list = Object(this);
var length = list.length >>> 0;
var thisArg = arguments[1];
var value;

for (var i = 0; i < length; i++) {
value = list[i];
if (predicate.call(thisArg, value, i, list)) {
return value;
}
}
return undefined;
};
}

IE alternative to Array.prototype.find()

You can create your own find function, the important part is to break loop when you match element.

var data = [{id: 1, name: 'a'}, {id: 2, name: 'b'}];
function altFind(arr, callback) { for (var i = 0; i < arr.length; i++) { var match = callback(arr[i]); if (match) { return arr[i]; } }}
var result = altFind(data, function(e) { return e.id == 2;})
console.log(result)

Convert object into array in IE (Javascript)

You can verify for yourself on On Mozilla's MDN that Array.from() isn't supported by IE :

Sample Image

On that same page, you can also find the following polyfill to add support of Array.from() to browsers that don't support it natively :

// Production steps of ECMA-262, Edition 6, 22.1.2.1
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;
};
}());
}

Note that it comes with the following remarks :

This algorithm is
exactly the one specified in ECMA-262, 6th edition, assuming Object
and TypeError have their original values and that callback.call
evaluates to the original value of Function.prototype.call. In
addition, since true iterables can not be polyfilled, this
implementation does not support generic iterables as defined in the
6th edition of ECMA-262.

That means that there are a few caveats, but it should be more than sufficient for most purposes!

TypeScript Array.from in IE11

It is a method that can be polyfilled.

Language features that can't be polyfilled are transpiled (if possible on the selected TypeScript target).

Map(iterable) alternative for IE 11

You say this is empty:

const map = new Map(Object.entries(array));

Have you tried just adding the values yourself?

const map = new Map();
Object.entries(array).forEach(entry => {
map.set(entry[0], entry[1]);
});

Object.entries() alternative for Internet Explorer and ReactJS

The usual first item to research when you want to use a newer API in an older browser is whether there is a simple polyfill. And, sure enough there is a pretty simple polyfill for Object.entries() shown on the MDN doc site:

if (!Object.entries)
Object.entries = function( obj ){
var ownProps = Object.keys( obj ),
i = ownProps.length,
resArray = new Array(i); // preallocate the Array
while (i--)
resArray[i] = [ownProps[i], obj[ownProps[i]]];

return resArray;
};


Related Topics



Leave a reply



Submit