splice(0) vs splice(0,undefined) - javascript

Splice with no second argument behaves as expected:
['a','b','c'].splice(0) // Returns ['a','b','c']
But Splice with a undefined second argument behaves differently:
['a','b','c'].splice(0, undefined) // Returns []
Can someone explain to me the difference? I would expect the same (first) result.
It suggests that internally, splice is using "arguments.length" or similar, to change its behaviour, rather than checking the arguments.

It suggests that internally, splice is using "arguments.length" or similar
Yes, that's exactly what happens internally.
If there is exactly one argument passed, it removes all elements until the end.
If there are more arguments passed, it takes the second one, casts it to an integer and uses it for the count of elements to be deleted. When you are passing undefined, it is cast to the number value NaN, which leads to the integer 0 - no elements are removed.

According to docs, Array.prototype.splice returns deleted elements.
It also says that when second parameter deleteCount equals 0 then nothing is deleted.
So, in the first case you are deleting everything after index 0 inclusive and the result is whole array.
In the second case you are deleting 0 elements and the result is empty array.

The reason the second result is empty is because, if the second parameter is 0 or negative, no elements are removed.
This is of course according to mozzila.

Syntax is:
splice(index, delete, insert)
There is condition actually "if delete part assigning "false" values which are (undefined, 0, false) it will return empty array".
That is why in second syntax returning blank array"
['a','b','c'].splice(0) //returns complete array
['a','b','c'].splice(0, undefined) // Returns []

Related

Why does calling pop on an empty array set the length to 0?

Given that the length of the array was already set to 0, why does pop set it to zero again?
Here are the first three steps of the ECMAScript 2023 spec for pop:
1. Let O be ? ToObject(this value).
2. Let len be ? LengthOfArrayLike(O).
3. If len = 0, then
a. Perform ? Set(O, "length", +0š¯”½, true).
b. Return undefined.
This seems redundant to me, which leads me to believe that I'm not understanding something.
Elsewhere in the spec the length property is re-set to zero (e.g. concat), and the reasoning is documented there:
The explicit setting of the "length" property in step 6 is necessary to ensure that its value is correct in situations where the trailing elements of the result Array are not present.
...and...
The explicit setting of the "length" property of the result Array in step 15 was necessary in previous editions of ECMAScript to ensure that its length was correct in situations where the trailing elements of the result Array were not present. Setting "length" became unnecessary starting in ES2015 when the result Array was initialized to its proper length rather than an empty Array but is carried forward to preserve backward compatibility.
Note how in pop the len value comes from LengthOfArrayLike which does more than just simply get the "length" property value: it coerces the type and restricts the range to integers.
...so the only situation in which it matters is if you have an almost Array-like object with a length property that returns a non-number value if empty:
let notArray = { length: "apples" };
console.log(notArray);
Array.prototype.pop.bind(notArray)();
console.log(notArray);
Because in both instances, the array was empty which always means the length is 0.
Pop on such an array of course will do nothing to increase the length, and so it remains 0.
It started at 0 for length. Pop will return nothing but it doesnā€™t leave the array undefined. Instead the array remains length 0.

How to use Array.push and return the pushed item?

I am calling return someArr[someArr.push(newItem)-1]; and it does pretty what it should.
Wondering is there a syntactic "sugar" for that extremely common operation? I wonder because returned new length is indeed more rarely needed, than actual constructed object (which caller definetely may want to polulate). Or is that made because it actually will return "a copy of an object", and my edits to its fields "will not survive" in actual tree?
Just like a JS <= 1.2 did: return someArr.push(newItem);
Just want to know - Is there are new "replacement" method, that I am unaware of?
Also I had a minor subquestion "does that return an 'independent' copy of an object or a 'reference' to actual object?" but simple fiddle by #PatricRoberts just figured out that it is actually a reference (as it was expected), so I've credited him, for his assistance!
You could also do it using a logical and (&&).
return someArr.push(newItem) && newItem;
Since the array length will be positive after the push, the right-most expression will be evaluated and its value returned.
This syntax is less clear than #adiga's answer using the comma operator though.
However, I personally prefer to return the new item on a new line to make it more readable:
someArr.push(newItem);
return newItem;
You could use the comma operator:
The comma operator evaluates each of its operands (from left to right) and returns the value of the last operand.
Like this:
return (someArr.push(newItem), newItem)
This is equivalent to:
someArr.push(newItem);
return newItem
You can do this by returning an assignment to the index of the current .length.
return someArr[someArr.length] = newItem;
The result of the assignment is the item being assigned, so that's what will be returned.
Assigning to the current .length of the array automatically expands it. Note that assigning to any index higher than the current .length will leave holes in the array.

How the order of arguments works in a reduce helper method?

// this is the array
var numbers = [10,20,30];
// Now I want to get the sum of all the elements of numbers array
// this will give 60
numbers.reduce(function(sum,number){
return sum + number;
},0);
// this also gives 60
numbers.reduce(function(number,sum){
return sum + number;
},0);
I am just learning ES6, I tried looking at MDN but couldn't find the explanation. I just want to know how javascript detects the argument with initial value to be zero and which it detects to be the array elements.
Or does it arbitrarily chooses the argument values.
According to MDN, the first argument will always be the sum/accumulator, and the second will be the value.
Both parameters have no inherit binding to a name, so you can name both the sum and the value whatever you wish.
In your example, the first one works probably as you expected, with the sum as the first parameter and the value as the second parameter. In your second example, it works the exact same way, the only difference being that you named the 'sum' as 'number' and the 'value' as 'sum'.
JS may be weird but it's not messing with your arguments in this case. You're just naming the arguments differently.
From MDN:
The first time the callback is called, accumulator and currentValue
can be one of two values. If initialValue is provided in the call to
reduce, then accumulator will be equal to initialValue, and
currentValue will be equal to the first value in the array. If no
initialValue is provided, then accumulator will be equal to the first
value in the array, and currentValue will be equal to the second.
Note: If initialValue isn't provided, reduce will execute the callback
function starting at index 1, skipping the first index. If
initialValue is provided, it will start at index 0.
The first param, "sum", is the accumulator. The second param, currentValue, is "number".
Here's the syntax of the reduce method.
array.reduce(function(total, currentValue, currentIndex, arr), initialValue)
where, function is used to reduce the array and will be invoked for each array element.
This function uses first argument passed to it as an accumulator to store the result.
Each element of the array will be passed as the second argument to the function.
Just like other functions in JavaScript, the order of the parameters matter(not their name).
While these two parameters are required to be present in your function, it can have two more optional parameters, viz currentIndex and the array itself.
And finally, the optional initValue passes to reduce function will be used to initialize the accumulator.
You can read more about it here.

Trying to understand how to use _.reduce

I'm trying to solve this question:
Use _.reduce to multiply all the values in an array.
Here's what I came up with:
var product = _.reduce([1, 2, 3], function(x, y){ return x * y; }, 0);
= 9
Is this close? I don't feel like I'm fulling grasping reduce(). Please help.
You should either omit the final 0 parameter from your call to _.reduce, or replace it with 1, depending on the semantics you want to achieve if you were to supply an empty array.
Rather than think of variables x and y in the callback, consider them as accumulator and current. In the first pass the "initial value" parameter is passed as accumulator, and in each subsequent pass the result of the previous pass is supplied as accumulator.
The 0 you erroneously supplied is passed as the first value of accumulator, and therefore every subsequent multiplication also results in 0.
Fortunately, the specification for reduce says that if you omit that initial value parameter then it will take the first element of the supplied array to be in the initial value for accumulator and then only iterate from the second element onwards.
If you don't supply an initial value then the array must have at least one element in it.

What internal method is calling in javascript when I get array element value by index?

I have some wtfjs code:
var a = [,];
alert(a.indexOf(a[0]));
a.indexOf(a[0]) returns -1. The main point in this example is difference between uninitialized and undefined values:
a contains one not initialized element.
a[0] return undefined.
a don't contains the undefined value. So a.indexOf(a[0]) === -1 is true.
But where I can find the explanation why a[0] return undefined? What internal method is calling?
P.S. Undefined is the javascript primitive type. Uninitialized means the value that don't have any javascript type, but there is no such primitive type in javascript.
The ES5 spec tells us the following of array initialisers:
Elided array elements are not defined.
Note that they are not defined. That's different from having the value undefined. As you've already noticed, elided elements do contribute to the length of the array:
...the missing array element contributes to the length of the Array and increases the index of subsequent elements.
When you invoke indexOf on an array this is one of the steps that happens:
Let kPresent be the result of calling the [[HasProperty]] internal method of O with argument ToString(k).
In that, k is a number corresponding to an array index and O is the array itself. Since elided elements were not defined the array does not have a property for the corresponding index.
The .indexOf() function only examines elements of the array that have explicitly been set. Therefore, in this case, even though the length of the array is 1 (or 2, depending on the browser involved), there are no explicitly-set elements, so the effective length is zero.
Another way of seeing this effect:
var a = [,];
console.log(a.length); // 1 (in Firefox)
console.log('0' in a); // false
That means that even though the length of the array is 1, there is no element with index 0. Thus, any explicit reference to examine the value of a[0] will have the value undefined.
Now, if we play a little more:
a[0] = undefined;
console.log(a.length); // still 1
console.log('0' in a); // true !!
Once the property reference has appeared on the left side of an assignment, it becomes "real" even if its (now explicit) value is undefined.
As for the "internal methods" involved, you can check the Reference Specification type, and in particular how its "Get" operation works.
This is a tricky one. For instance, if you set a = [,,1] and examine the array, you'll see that only the index of 2 has a value, and it is 1. Index 0 & 1 have no value at all, they were implicitly set to undefined. In other words, they are NOT DEFINED. If you search for a value of undefined in an array, it will always return -1. If you instead set them explicitly to null, you'll see your index come back.
To directly address your question, a.indexOf(a[0]) returns -1 because a[0] is undefined.
All elements of an array which are not defined as a value (including null) are undefined.
When you define an array like this:
var a = [,null,];
Elements a[0] and a[2] are undefined. Any index you use into the array a will return undefined except a[1] which is null. The length property of an array is one higher than the highest non-undefined index. For example:
var b = [];
b[10] = null;
b.length
> 11
However the only index which will not return undefined is b[10].
You can read more about it here:
http://msdn.microsoft.com/en-us/library/d8ez24f2(v=vs.94).aspx
I am not sure what you mean by uninitialized - I think that concept is captured by undefined in JavaScript.

Categories

Resources