About pop() and push() in Javascript - javascript

I'm really a beginner in Javascript, and trying what i read as much as I can.
But when comes to pop() and push(), I get some strange results that I'm wondering about.
Here's the code :
var arr = [];
arr.push(2,3);
console.log(arr);
console.log(arr.pop());
console.log(arr);
the result is :
[2, undefined × 1]
3
[2]
Shouldn't it be :
[2, 3]
3
[2]

This is due to console.log's asynchronous evaluation on your browser. By the time the result of the first console.log has been displayed, the item is already gone because of pop().
For accurate results, call toString():
var arr = [];
arr.push(2,3);
console.log(arr.toString()); // 2,3 - as expected.
console.log(arr.pop());
console.log(arr);

You'd have to note that the console handles objects as "live". Any object (arrays, objects etc.) you already outputted on the console is still subject to operations.
That's why when you expected [2,3] on the first log, the code already popped the 3, thus replaced undefined on 3's spot.
Of course, this event depends on how the browser implement's their console.

Related

Why is destructuring and concatenation leaving different types of undefined in array? [duplicate]

I'm doing some small experiments based on this blog entry.
I am doing this research in Google Chrome's debugger and here comes the hard part.
I get the fact that I can't delete local variables (since they are not object attributes). I get that I can 'read out' all of the parameters passed to a function from the array called 'arguments'. I even get it that I can't delete and array's element, only achieve to have array[0] have a value of undefined.
Can somebody explain to me what undefined x 1 means on the embedded image?
And when I overwrite the function foo to return the arguments[0], then I get the usual and 'normal' undefined.
This is only an experiment, but seems interresting, does anybody know what undefined x 1 refers to?
That seems to be Chrome's new way of displaying uninitialized indexes in arrays (and array-like objects):
> Array(100)
[undefined × 100]
Which is certainly better than printing [undefined, undefined, undefined,...] or however it was before.
Although, if there is only one undefined value, they could drop the x 1.
Newer versions of Chrome use empty instead of undefined to make the difference a bit clearer.
For example, entering [,,undefined,,] in the DevTools console results in:
▼(4) [empty × 2, undefined, empty]
2: undefined
length: 4
▶__proto__: Array(0)
Google Chrome seems to choose to display sparse array using this undefined x n notation. It will show [undefined, undefined] if it is not a sparse array:
var arr = new Array(2);
console.log(arr);
var arr2 = [];
arr2[3] = 123;
console.log(arr2);
var arr3 = [,,,];
console.log(arr3)
var arr4 = [,];
console.log(arr4)
var arr5 = [undefined, undefined]
console.log(arr5)
var arr6 = [undefined]
console.log(arr6)
arr1 to arr4 are all sparse arrays, while arr5 and arr6 are not. Chrome will show them as:
[undefined × 2]
[undefined × 3, 123]
[undefined × 3]
[undefined × 1]
[undefined, undefined]
[undefined]
note the [undefined x 1] for the sparse array.
Since you deleted an element, it follows that: If you delete an element from an array, the array becomes sparse.
Here is how it looks, Type this code into chrome devtools console:-
arr = new Array(4);
arr[2] = "adf";
console.log(arr); // [undefined × 2, "adf", undefined × 1]
See the first two consecutive "undefined" that are represented by *2, to show that there are two consecutive undefined there
It just happened to me too. Open the same thing in another browser and output/log the array to the console. As long as it works in both crome and in firefox the same way (as in accessing the elements works fine even if the output has the undefinedx1), I consider it some kind of bug in Chrome not refreshing something internally. You can actually test it this way:
I was adding elements to an array, and firing console.log() to log the element, to check if it was undefined or not. They were all defined.
After push() I logged the array and it seemed that when this happened, it was always the last one being undefined x 1 on Chrome.
Then I tried logging it more times and also later, but with the same result.
However when I accessed (for the sake of output), the element by its index, it returned the proper value (funny).
After that I logged the array again and it said the last index was undefined x 1 (the very one I just accessed directly with success!).
Then I did a for loop on the array, logging or using each element, all showed up fine.
Then another log on the array, still buggy.
The code I'm originally using has checks for undefined and they didn't fire, but I was seeing all these undefineds in the console and it was bugging me (no pun intended).
Also worth reading: Unitialized variables in an array when using only Array.push? I'm using pop() too in my code and it's a reasonable explanation that the console log actually represents a different state in time (when the code is 'halted').

Javascript - what should setting a value at index -1 in an array do?

I've been surprised to find that:
var a = [1, 2, 3];
a[-1] = 4;
can have different results:
in chrome -> a is then [1, 2, 3]
in node -> a is then [1, 2, 3, '-1': 4]
what is the expected behavior, if any?
The result should be the same no matter what. Either one may display differently in the console, but in practice, the fashion in which values are displayed in the console shouldn't really have any bearings on the underlying mechanics. In this case, the effect is the same: the property named -1 is set to 4. However, you won't be able to iterate through this normally, unless you specifically set your start value to -1, and the value at -1 very probably (don't quote me on this) won't be reflected in the array's length property.
If you're interested, the ECMAScript specification for Arrays is here:
http://ecma-international.org/ecma-262/7.0/index.html#sec-array-objects
and the length property of Array instances is defined here:
http://ecma-international.org/ecma-262/7.0/index.html#sec-properties-of-array-instances-length

What delete really means in NodeJS in arrays?

Reading the answers to this question I understand that delete sets undefined value for the element.
So, if we have an array: a = [1, 2, 3] (at least) on the client side using delete a[1] the array would become [1, undefined x 1, 3] that is true, on the client side.
What happens in NodeJS?
But testing same operation on NodeJS (server side) I get the following:
$ node
> a = [1, 2, 3]
[ 1, 2, 3 ]
> delete a[1]
true
> a
[ 1, , 3 ]
> a[1] = undefined
undefined
> a
[ 1, undefined, 3 ]
>
So, a[1] = undefined sets undefined value. But what does the space mean between the two commas ([1, , 3])? delete put it! Why?
I guess that the space means undefined, but why it doesn't appear as undefined only I set it as undefined?
Why is this happening?
When you use delete on an array entry, it removes that entry from the array. The array length is not changed, but that slot in the array is gone. If you try to look at the value of that slot it will show as undefined though deleting it is not quite the same as setting it to undefined. You can read about deleting an array entry here (scroll down to the subtitle "Deleting Array Elements").
This reference also explains the difference between using delete on an array entry vs. setting it to undefined. The difference is subtle and only makes a difference in a few situations. Here's an example from that article:
// using delete
var trees = ["redwood","bay","cedar","oak","maple"];
delete trees[3];
if (3 in trees) {
// this does not get executed
}
// setting to undefined
var trees = ["redwood","bay","cedar","oak","maple"];
trees[3]=undefined;
if (3 in trees) {
// this gets executed
}
So, this console output:
[ 1, , 3 ]
is showing you that the second array entry is missing (it's gone completely).
See this article http://perfectionkills.com/understanding-delete/ for a full run-down of how the delete operator works in other circumstances.
Array indexes at language level work like any other properties.
When you access a property that's not there, the proto chain is walked until a result is found or undefined is returned if nothing is found. But you can also use undefined as a normal value.
There can be major differences, eg:
Array.prototype[1] = 15;
var a = [1, 2, 3];
delete a[1];
//protip: the above can be written as `var a = [1,,3]`
var b = [1, undefined, 3];
//Logs 15 and undefined
console.log(a[1], b[1]);
In a, because the property 1 is not there, the prototype is checked and the value 15 is found.
In b, because the property 1 is there, the value of the property (undefined) is just directly returned.
Also the console formatted output for an array is usually different between environments but that doesn't really change what is actually going on.

Javascript Array logging confusion

I have noticed something that I cannot understand at all. I am doing something really simple in JavaScript:
var a = [1,2,3];
console.log(a.push(4));
console.log(a);
console.log(a.push(5));
I would expect the console to log: 4, [1,2,3,4], and 5 as described here for example.
The catch is that the actual console output looks like: 4, [1,2,3,4,5], and 5
See: http://jsfiddle.net/HknMF/
What on earth makes the 5 appear in the second log output?
EDIT: fwiw here's a screenshot of Firebug showing both behaviors: http://i.imgur.com/fwAK3.png
​
The console in some browsers uses a reference to the array/object, so when you inspect it and the object changed after the console.log() call you'll see the changed object.
In Firefox this also happens for objects, but not for arrays which are displayed inline anyway:
>>> var a = [1,2,3]; console.log(a.push(4)); console.log(a); console.log(a.push(5));
4
[1, 2, 3, 4]
5
Especially for objects that do not contain functions a quick workaround is either cloning them (log $.extend({}, yourObject) if you have jQuery) or logging their JSON string version (then you lose the nice object view and just get a plain string though). An array can easily cloned (shallow copy!) using a.slice(0)
Dependent of the Browser either your live array gets logged (Chrome) or A string representation (Firefox).
A shallow copy is sufficient to prevent that. Use:
console.log( a.slice(0) );
for that.

Pushing items on stack and logging the current stack in a for(each) loop

I've got the following problem and I can't seem to get why it's not working the way I think it should be working:
function iterate(somelist){
anotherlist = [];
for(i = 0; i < somelist.length; i++){
anotherlist.push(somelist[i]);
console.log(anotherlist);
}
}
What I would expect this to do is log an increasingly growing list, but instead it just prints the complete list several times, as if it first pushes all variable into anotherlist and afterwards starts the log function. It doesn't seem to matter wether I use a for or a foreach loop.
I really don't get why it works like this and can't seem to figure out a way to work around it.
Thanks in advance,
Bart
By the way, somelist in this case is an object on which I iterate, and it seems to make a difference, as I tried it with a normal array and that seems to work.
you might want to console log the new list
console.log(anotherlist);
I suspect the console waits for the thread to finish before updating, perhaps so as not to interfere with performance too much. When the console UI is finally updated, the thread (and loop) has already finished and all logs reference the same array.
To work around it, you can call the array's slice() method to make a copy of the array whilst logging:
function iterate(somelist){
anotherlist = [];
for(i = 0; i < somelist.length; i++){
anotherlist.push(somelist[i]);
console.log(anotherlist.slice());
}
}
var test = [1, 2, 3, 4];
iterate(test);
//-> [1]
//-> [1, 2]
//-> [1, 2, 3]
//-> [1, 2, 3, 4]
By the sound of it you are getting confused about for(;;) and for(in) loops.
For loops are just the same old loop you know from C, Java or basically any language out there. Create a loop variable, increment it, etc.
Of course, you probably can't iterate over an object with a for-loop though because you need to have a .length property...
for(in) loops are not foreach loops! (This confusion is a very common Javascript trap)
for-in iterates over object properties and thus should only be used to iterate on Objects, not array. For example:
var xs = {
a : 1,
b : 2
};
for(var i in xs){
console.log(i, xs[i])
}
will print
'a', 1
'b', 2

Categories

Resources