Question:
Many people ask how to turn NodeList, HTMLColletion and other pseudo-array into Array. So I need the opposite. That is, I need to turn an Array, for example, into a NodeList.
How to do it?
There are two "buts":
- I don't know what exactly I have: NodeList, HTMLColletion or some other pseudo-array; but I have a pseudo-array with that proto to turn the array into.
- Do not offer options with a change through the
__proto__
parameter, since I need an option that will work at least in IE10
Answer:
Unfortunately, there is no way to artificially create a pseudo-array (array-like object) like NodeList and HTMLCollection, even with the help of the __proto__
property.
When you change the __proto__
of an array, it will simply change the "parent" from Array
to whatever you specify when you change it. This will change the standard properties from Array.prototype
to [{Object}].prototype
.
var elements = document.querySelectorAll('div'); var array = [document.querySelector('div')]; // Изменяем прото массива array.__proto__ = NodeList.prototype; // Проверяем содержимое обоих элементов console.log(elements); // [<div></div>, item, entries, forEach, keys, values] console.log(array); // [<div></div>, item, entries, forEach, keys, values] // Провряем тип элементов console.log({}.toString.call(elements)); // [object NodeList] console.log({}.toString.call(array)); // [object NodeList] // Но тут сюрприз console.log(Array.isArray(elements)); // false console.log(Array.isArray(array)); // true
<div></div>
As you can see from the example, the array has not ceased to be an array, but purely visually and by the type of object, it looks like a NodeList.
Technically, a pseudo-array can be any object that has a length property internally, which must be a positive integer. At least Array.from()
pays attention mainly to this property.
Object.canAccessAsArray = function(object) { return Number.isInteger(Number(object.length)) && Number(object.length) >= 0; }; // Тут выдаст массив с тремя пустыми значениями console.log( Object.canAccessAsArray({length: 3}) + ' => ' + Array.from({length: 3}) ); // А тут есть значения console.log( Object.canAccessAsArray({'0': 'a', '1': 'b', '2': 'c', length: 3}) + ' => ' + Array.from({'0': 'a', '1': 'b', '2': 'c', length: 3}) ); // А тут будет пустой массив, из за отсутствия length console.log( Object.canAccessAsArray({'0': 'a', '1': 'b', '2': 'c'}) + ' => ' + Array.from({'0': 'a', '1': 'b', '2': 'c'}) );