Apologize in advance for lengthy post. I am trying to understand array reduce polyfill provided by MDN. I could not understand some lines in the polyfill can you explain it please. Below is the code
if (!Array.prototype.reduce) {
Object.defineProperty(Array.prototype, 'reduce', {
value: function(callback /*, initialValue*/) {
if (this === null) {
throw new TypeError( 'Array.prototype.reduce ' +
'called on null or undefined' );
}
if (typeof callback !== 'function') {
throw new TypeError( callback +
' is not a function');
}
// 1. Let O be ? ToObject(this value).
var o = Object(this);
// 2. Let len be ? ToLength(? Get(O, "length")).
var len = o.length >>> 0;
// Steps 3, 4, 5, 6, 7
var k = 0;
var value;
if (arguments.length >= 2) {
value = arguments[1];
} else {
while (k < len && !(k in o)) {
k++;
}
// 3. If len is 0 and initialValue is not present,
// throw a TypeError exception.
if (k >= len) {
throw new TypeError( 'Reduce of empty array ' +
'with no initial value' );
}
value = o[k++];
}
// 8. Repeat, while k < len
while (k < len) {
// a. Let Pk be ! ToString(k).
// b. Let kPresent be ? HasProperty(O, Pk).
// c. If kPresent is true, then
// i. Let kValue be ? Get(O, Pk).
// ii. Let accumulator be ? Call(
// callbackfn, undefined,
// « accumulator, kValue, k, O »).
if (k in o) {
value = callback(value, o[k], k, o);
}
// d. Increase k by 1.
k++;
}
// 9. Return accumulator.
return value;
}
});
}
Question1: If you see step 1,
var o = Object(this);
I have checked both values of o and this, by passing an array to the polyfill method. There is no difference between o and this. They both are arrays(array.isarray returned true on both) with the same array value. Why not use below instead..?
var o = this;
Question2: Step 2
var len = o.length >>> 0;
Above line seems to right shift the o.length(32 bits). However no.of bits shifted is 0. So what advantage do we get by shifting 0 bits... Why not use below instead...?
var len = o.length;
Question 3: The first while condition inside else as below
while (k < len && !(k in o)) {
k++;
}
Initially k is set to 0 and it always seems to exist in o. So this while loop condition never gets to be true. So why do we need this while loop, if it never gets inside.
Question 1:
To make sure reduce
is called on an object as reduce could be called through Function#call
, Function#apply
or even bound Function#bind
:
Array.prototype.reduce.call(undefined, function() {});
So when accessing properties such as length
, an error saying can't access property **** of undefined
won't be thrown.
NOTE: the example above uses the native reduce
which actually throws an error if not provided with an object.
Question 2:
To always have a valid integer value as length
(even if it doesn't exist):
console.log(5 >>> 0); // 5
console.log(5.5 >>> 0); // 5
console.log("5" >>> 0); // 5
console.log("hello" >>> 0); // 0
console.log(undefined >>> 0); // 0
Question 3:
To deal with sparse arrays:
var arr = [5, 6];
arr[7000000] = 7;
arr.reduce(function(acc, v, i) {
console.log("index:", i);
}, 0);
It won't go through all the indices from 0
to 7000000
, only those that really exist.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With