Javascript new keyword .length not working - javascript

Hoping someone can shed some light on this simple piece of code not working as expected:
var arr = new Array(10);
arr.length; // 10. Why? Very wierd.
Why does it return 10?

You instantiated the array with ten elements

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array
If the only argument passed to the Array constructor is an integer
between 0 and 232-1 (inclusive), this returns a new JavaScript array
with its length property set to that number
So it is impossible to create a new array with only one number element using the new keyword.
You can however do :
var arr = [10]; // Creates a new array with one element (the number 10)
console.log(arr.length); // displays 1 because the array contains one element.

I makes an Array with 10 cells... so it returns 10 :)
You wanted to do:
var arr = [10]

It returns 10, because you give only one integer, as argument, to the Array constructor. In this case, the new Array constructor is acting like some programming languages where you needed to specify the memory for your array so you don't get those ArrayIndexOutOfBounds Exceptions.
An example of this in Java:
int[] a = new int[10];
Or C#:
int[] array = new int[5];
In Javascript, when you write:
var a = new Array(10);
a[0] // returns undefined
a.length // returns 10.
and if you write:
a.toString() // returns ",,,,,,,,,", a comma for each element + 1
But, since Javascript doesn't need to allocate memory for an array, is better to use use the [] constructor:
var a = [10];
a[0] //returns 10
a.length //returns 1
I think that the thing that confuse all the people is this:
var a = new Array(1,2,3,4,5);
a[0] // returns 1
a.length // returns 5
But you can do the same in this way:
var a = [1,2,3,4,5];
a[0] // returns 1
a.length // returns 5
So, in conclusion, try to avoid using the new Array constructor, and use the [] constructor instead.

Related

.map not working as expected on uninitiated array

Using .map() on an array full of undefined values (eg new Array(10)) will always return an array of the same length with undefined values, no matter what you return.
new Array(10).map(function(){return 5;});
will return a new array filled with 10x undefined. Why does this happen?
Because when you define an array like that, the spaces for values are empty slots and are not iterated over by map() or any of its friends.
There is Array.prototype.fill() (in ES6) which can be used to set values on that array.
You could use
var array = Array.apply(null, { length: 10 }).map(function(){ return 5; });
var array = Array.apply(null, { length: 10 }).map(function() { return 5; });
document.write('<pre>' + JSON.stringify(array, 0, 4) + '</pre>');
from the fine manual:
map calls a provided callback function once for each element in an array, in order, and constructs a new array from the results. callback is invoked only for indexes of the array which have assigned values, including undefined. It is not called for missing elements of the array (that is, indexes that have never been set, which have been deleted or which have never been assigned a value).
new Array(10)
creates missing elements, if that makes any sense.
Like this one:
var b=new Array();
b[30] = 1;
var c = b.map(function(){return 5;});
> [undefined × 30, 5]
There's an answer for this here: https://stackoverflow.com/a/5501711/6206601. Look at the top comment for further clarification.

Array of length bracket notation

If I want to make an array that is say of length 3 using bracket notation, should I just write: var foo = [,,];
I was more used to writing: var foo = new Array(3);
I noticed that if I removed one , that my code still worked which is surprising because I am accessing all 3 elements after assigning them. How is it that it would still work?
if u do
a = []
a[3] = 100
the indices 0,1,2 will be filled in with undefined for u. u do not have to set a specific array length before using certain indices. array will grow as u use it.
all these are the same:
a = [,,,]
b = []
b.length = 3
c = new Array(3)
d = []
d[2] = undefined

Confused by behavior of `map` on arrays created using `new` [duplicate]

This question already has answers here:
Undefined values in Array(len) initializer
(5 answers)
Closed 7 years ago.
I am confused by the results of mapping over an array created with new:
function returnsFourteen() {
return 14;
}
var a = new Array(4);
> [undefined x 4] in Chrome, [, , , ,] in Firefox
a.map(returnsFourteen);
> [undefined x 4] in Chrome, [, , , ,] in Firefox
var b = [undefined, undefined, undefined, undefined];
> [undefined, undefined, undefined, undefined]
b.map(returnsFourteen);
> [14, 14, 14, 14]
I expected a.map(returnsFourteen) to return [14, 14, 14, 14] (the same as b.map(returnsFourteen), because according to the MDN page on arrays:
If the only argument passed to the Array constructor is an integer
between 0 and 2**32-1 (inclusive), a new JavaScript array is created
with that number of elements.
I interpret that to mean that a should have 4 elements.
What am I missing here?
When you create an array like so:
var arr1 = new Array( 4 );
you get an array that has a length of 4, but that has no elements. That's why map doesn't tranform the array - the array has no elements to be transformed.
On the other hand, if you do:
var arr2 = [ undefined, undefined, undefined, undefined ];
you get and array that also has a length of 4, but that does have 4 elements.
Notice the difference between having no elements, and having elements which values are undefined. Unfortunately, the property accessor expression will evaluate to the undefined value in both cases, so:
arr1[0] // undefined
arr2[0] // undefined
However, there is a way to differentiate these two arrays:
'0' in arr1 // false
'0' in arr2 // true
var a = new Array(4);
This defines a new array object with an explicit length of 4, but no elements.
var b = [undefined, undefined, undefined, undefined];
This defines a new array object with an implicit length of 4, with 4 elements, each with the value undefined.
From the docs:
callback is invoked only for indexes of the array which have assigned
values; it is not invoked for indexes which have been deleted or which
have never been assigned values.
For array a, there are no elements that have been assigned values, so it does nothing.
For array b, there are four elements that have been assigned values (yes, undefined is a value), so it maps all four elements to the number 14.
new Array(len) creates an empty array, and does something different than filling it with undefined values: It sets its length to len. So, it translates to this code:
var newArr = [];
newArr.length = len;
Let's have some fun with newArr (assuming that len = 4):
newArr.length; //4
newArr[1] === undefined; //true
newArr.hasOwnProperty(1); //false
This is because while the is 4 items long, it does not contain any of these 4 items. Imagine an empty bullet-clip: It has space for, say, 20 bullets, but it doesn't contain any of them. They weren't even set to the value undefined, they just are...undefined (which is a bit confusing.)
Now, Array.prototype.map happily walks along your first array, chirping and whistling, and every time it sees an array item, it calls a function on it. But, as it walks along the empty bullet-clip, it sees no bullets. Sure, there are room for bullets, but that doesn't make them exist. In here, there is no value, because the key which maps to that value does not exist.
For the second array, which is filled with undefined values, the value is undefined, and so is the key. There is something inside b[1] or b[3], but that something isn't defined; but Array.prototype.map doesn't care, it'll operate on any value, as long as it has a key.
For further inspection in the spec:
new Array(len) : http://es5.github.com/#x15.4.2.2
Array.prototype.map : http://es5.github.com/#x15.4.4.19 (pay close attention to step 8.b)
One additional answer on the behavior of console.log. Plain simple, the output is sugar and technically wrong.
Lets consider this example:
var foo = new Array(4),
bar = [undefined, undefined, undefined, undefined];
console.log( Object.getOwnPropertyNames(bar) );
console.log( Object.getOwnPropertyNames(foo) );
As we can see in the result, the .getOwnPropertyNames function returns
["length"]
for the foo Array/Object, but
["length", "0", "1", "2", "3"]
for the bar Array/Object.
So, the console.log just fools you on outputting Arrays which just have a defined .length but no real property assignments.

What is the way of declaring an array in JavaScript?

I'm just learning JavaScript and it seems like there are a number of ways to declare arrays.
var myArray = new Array()
var myArray = new Array(3)
var myArray = ["apples", "bananas", "oranges"]
var myArray = [3]
What are their difference, and what are the preferred ways?
According to this website the following two lines are very different:
var badArray = new Array(10); // creates an empty Array that's sized for 10 elements
var goodArray= [10]; // creates an Array with 10 as the first element
As you can see these two lines do two very different things. If you
had wanted to add more than one item then badArray would be
initialized correctly since Javascript would then be smart enough to
know that you were initializing the array instead of stating how many
elements you wanted to add.
Is what the authors trying to say is Array(10) creates an array with precisely 10 elements and [10] creates an array of undefined size with the 0th element being 10? Or what does this mean?
In your first example, you are making a blank array, same as doing var x = []. The 2nd example makes an array of size 3 (with all elements undefined). The 3rd and 4th examples are the same, they both make arrays with those elements.
Be careful when using new Array().
var x = new Array(10); // array of size 10, all elements undefined
var y = new Array(10, 5); // array of size 2: [10, 5]
The preferred way is using the [] syntax.
var x = []; // array of size 0
var y = [10] // array of size 1: [1]
var z = []; // array of size 0
z[2] = 12; // z is now size 3: [undefined, undefined, 12]
The preferred way is to always use the literal syntax with square brackets; its behaviour is predictable for any number of items, unlike Array's. What's more, Array is not a keyword, and although it is not a realistic situation, someone could easily overwrite it:
function Array() { return []; }
alert(Array(1, 2, 3)); // An empty alert box
However, the larger issue is that of consistency. Someone refactoring code could come across this function:
function fetchValue(n) {
var arr = new Array(1, 2, 3);
return arr[n];
}
As it turns out, only fetchValue(0) is ever needed, so the programmer drops the other elements and breaks the code, because it now returns undefined:
var arr = new Array(1);
To declare it:
var myArr = ["apples", "oranges", "bananas"];
To use it:
document.write("In my shopping basket I have " + myArr[0] + ", " + myArr[1] + ", and " + myArr[2]);
There are a number of ways to create arrays.
The traditional way of declaring and initializing an array looks like this:
var a = new Array(5); // declare an array "a", of size 5
a = [0, 0, 0, 0, 0]; // initialize each of the array's elements to 0
Or...
// declare and initialize an array in a single statement
var a = new Array(0, 0, 0, 0, 0);
If you are creating an array whose main feature is it's length, rather than the value of each index, defining an array as var a=Array(length); is appropriate.
eg-
String.prototype.repeat= function(n){
n= n || 1;
return Array(n+1).join(this);
}
You can declare like this
const [alice, bob] = [1, 2]
console.log(alice) // 1
console.log(bob) // 2

javascript/jQuery Array concatenation?

I have some simple jQuery code:
var response = Array()
$('.task-list').each(function() {
response.concat(response,$('#' + this.id).sortable('toArray'));
}
);
console.log(response);
The problem I'm having is that I think I'm using concat improperly- the result is an empty array. When I use array push, it works correctly.
You have to set response to the newly formed array, as described in the specification. You currently don't use the return value at all.
The specification says that for .concat, the array is not altered, but the new array is returned:
When the concat method is called with zero or more arguments item1, item2, etc., it returns an array containing the array elements of the object followed by the array elements of each argument in order.
Compare with .push, which says the current array is altered, and that something else is returned instead (the new length):
The arguments are appended to the end of the array, in the order in which they appear. The new length of the array is returned as the result of the call.
So:
response = response.concat($('#' + this.id).sortable('toArray'));
Concat returns the concatenated array, you want this instead
response = response.concat($('#' + this.id).sortable('toArray'));
Simple example
var a = [1,2];
var b = [3,4];
a = a.concat( b ); // result is [1,2,3,4] which is correct
If you do the following
a = a.concat( a , b ); // result is [1, 2, 1, 2, 3, 4] not what you want.

Categories

Resources