⬆️ ⬇️

A little bit about pseudo-arrays (mass-like objects or collections). “What is this?”, “How to work with them?” And so on

In this article I will talk about pseudo-arrays: “What is it?”, “How to work with them?”, “How do they differ from an array?”, “How to convert them into an array?”.



Also, before you begin, I will clarify that this information applies only to JavaScript. That is, I will talk about pseudo-arrays in JavaScript.



What is a pseudo-array (a mass-like object or collection)?



A pseudo-array is an object that is structurally similar to an array. That is, it has numeric properties (indices) and the length property.

')

Example:

 {0: ' 1', 1: ' 2', 2: ' 3', length: 3}; 


How does a pseudo-array differ from an array?



The main difference between a pseudo-array and an array is its prototype inheritance, that is, the __proto__ property.



When we look at the properties of an array, we see that it inherits the prototype of the Array object. That is, all properties that are in the Array.prototype object will be available for any array. If you look at the properties of any pseudo-array, then you will notice that it inherits the prototype of another object along with other properties.



List of pseudo-array object types



A pseudo-array can inherit prototypes of various objects. Here is a small list of object types - pseudo-arrays:





This is a small part of the complete list of types of pseudo-arrays, which has more than fifty types in it. From this follows the next paragraph of the article.



How to distinguish a regular object from a pseudo-array?



For three days I examined this question by reading various articles and as a result I made only one condition: if an object is a pseudo-array, then it must have the length property, which must be an integer and be greater than or equal to zero.



 Number.isInteger(Number(object.length)) && Number(object.length) >= 0 


I made this condition by discarding the following items:



  1. You can not be equal to the numerical properties, because if you do not specify them, it does not mean that they will not. They will simply be equal to undefined
  2. When I looked at the types of pseudo-arrays, I saw that their types contained the word Collection , Map or List . But this idea was immediately dispelled, since a pseudo-array can be of the usual object type - Object ,

    and in general it is stupid, because even an ordinary array will not fall under this item.
  3. It is also impossible to be equal to non-numeric properties, because a non-numeric property can also be in an array.


But JavaScript “said” that my condition is too cruel. When I analyzed the options for converting a pseudo-array into an array, I realized that JavaScript would “eat” a pseudo-array in which the length property is equal to a number that is greater than or equal to zero.



 typeof object.length === 'number' && Number(object.length) >= 0 


And it is not necessary that the number be an integer (except in some cases). JavaScript will simply convert a fractional number to the largest integer, less than or equal to the specified one.



Example:

 Array.from({0: ' 1', 1: ' 2', length: 1.6}); // [' 1'] Array.from({0: ' 1', 1: ' 2', 2: ' 3', length: 2.3}); // [' 1', ' 2'] 


How to convert a pseudo-array into an array?



To transform a pseudo-array into an array, there are several options:



  1. Enumerate pseudo-array values ​​into a regular array

    The first option that comes to mind for beginners is to loop through all the values ​​from a pseudo-array into an array using a loop.



     var object = {0: 1, 1: 2, 2: 3, length: 3} var array = []; //     for (var i = 0; i < object.length; i++) { array.push(object[i]); }; console.log( array ); // [1, 2, 3] 


  2. Using the Array.from() Function

    This option is a bit controversial, since the tables, browser support for this function, on different sites are different. But I can say with confidence that this method will work in all modern browsers.



     var object = {0: 1, 1: 2, 2: 3, length: 3} //     var array = Array.from(object); console.log( array ); // [1, 2, 3] 


  3. Using the Array.prototype.slice.call() ( [].slice.call() ) [].slice.call()

    This method of "our grandparents", which still works today.



     var object = {0: 1, 1: 2, 2: 3, length: 3} //     var array = Array.prototype.slice.call(object); //   : [].slice.call(object); console.log( array ); // [1, 2, 3] 


  4. Using the spread operator

    This method is rather controversial at the time of this writing, as it is not supported by all browsers so far and will work only with “root” pseudo- NodeList ( NodeList , HTMLCollection , etc.).



     var object = document.querySelectorAll(selector); //     var array = [...object]; console.log( array ); // [element, element, element] 


  5. By changing the __proto__ property

    I mentioned this property at the beginning of the article. If we change the property of the __proto__ object to Array.prototype , then the pseudo-array is converted to an array. But this method is included in those “except for some cases” about which I wrote above, since, for a complete transformation into an array, the length property must be an integer.



     var object = {0: 'a', 1: 'b', 2: 'c', length: 3} //  __proto__  object.__proto__ = Array.prototype; console.log(object); // ['a', 'b', 'c'] 


    There is also one feature here: if we specify a length number, which will be less than the number of records in the pseudo-array, then we will have an array with the number of records specified in length and with additional properties from the rest of the records.



     var object = {0: 'a', 1: 'b', 2: 'c', 3: 'd', 4: 'e', length: 3} //  __proto__  object.__proto__ = Array.prototype; console.log(object); // ['a', 'b', 'c', 3: 'd', 4: 'e'] 


    And one more note: this method will not make the object a real array, although it will give it the necessary parameters. You can verify this by checking the object using the Array.isArray(); function Array.isArray(); .



     var object = {0: 'a', 1: 'b', 2: 'c', 3: 'd', 4: 'e', length: 3} //  __proto__  object.__proto__ = Array.prototype; console.log( Array.isArray(object) ); // false 




These are the most popular conversion methods. You also need to say that you can not use all these methods if you need, for example, to iterate over a pseudo- forEach using forEach or filter it with the filter function. For such purposes, functions have an additional function .call() , which makes it possible to work with pseudo-arrays.



Example:

 var object = {0: 'a', 1: 'b', 2: 'c', length: 3} //      object = Array.prototype.map.call(object, v => ': ' + v); //  : [].map.call(object, v => ': ' + v) console.log(object); // [': a', ': b', ': c'] 


On this I finish this article. He told what he wanted, and whether it was useful for you, you decide.

Source: https://habr.com/ru/post/336136/



All Articles