Hole in arrays versus undefined and mapping functions

I understand that map not called in undefined indexes on arrays, and I appreciate that the undefined index is different from the index of the array, explicitly assigning the value "undefined" (that is, right?). However, how should you distinguish between holes in an array and undefined values?

Code below:

foo.js

 var arr = [,,undefined,,,,3,,,4]; console.log("A hole the same as undefined? "+(arr[0]===undefined?"yes":"no")); var _ignored = arr.map(function(x) {console.log("f called on ["+x+"]");}); 

... creates at startup:

 $ node foo.js A hole the same as undefined? yes f called on [undefined] f called on [3] f called on [4] 

... similar results should be obtained when replacing map with forEach .

+5
source share
2 answers

The in operator tells you whether the index is actually assigned:

 a = [] a[5] = window.foo document.write(a[4] + "<br>") document.write(a[5] + "<br>") document.write((4 in a) + "<br>") document.write((5 in a) + "<br>") 

Javascript arrays are actually objects with a special length property, and array indices are just property names (in fact, they are strings, not numbers inside). Thus, the above definition is equivalent to:

 a = { 5: window.foo, length: 6 } 

Therefore, all the functional functions of objects associated with keys (for example, in , hasOwnProperty , Object.keys ) also work for array indices.

forEach and other iteration methods work by iterating from 0 to length-1 and checking if the nth index is actually present in the argument , they don’t β€œknow” if the argument is actually an array or just a common object:

 a = {1:'one', 5:'five', length:100}; [].forEach.call(a, function(x) { document.write(x) }); 
+6
source

What you call a β€œhole” is not an exact hole:

 var a = [,,,,,,,,,,]; a.length; // 10 var n, k; n=0; for (k in a){if (a.hasOwnProperty(k)){++n;}else{break;}}; n; // 10 : a has 10 own properties, all SET to undefined 

Now remove all properties and recount

 while (n--) delete a[n]; for (k in a){if (a.hasOwnProperty(k)){++n;}else{break;}}; n; // 0 a.length; // 10 : a is identical to Array(10), empty array of length 10 

To get an array with holes, you can either delete the properties manually, or start with Array (N) and populate some indexes with values, or use push / splice, but not the methods that return the array. For instance:

 Array(2).concat([void(0)]).concat(Array(3)).concat([3]).concat(Array(2)).concat([4]); 

reproduces exactly your original array (it has a length of 10 and 10 of its own properties), although the first term (Array (2)) does not.


EDIT . The above version has been tested in ExtendScript and is not true in recent browsers (see comments). Tested subsequently in Firefox and [,,,] really does not have its own property ...

-1
source

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


All Articles