Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Correct implementation of Array.from and Array.of as they are currently spec'ed. Includes "isConstructor"
(function( global ) {
"use strict";
function isConstructor( C ) {
try {
new C();
return true;
} catch ( e ) {
return false;
}
}
Array.from = function( arrayLike ) {
var items, len, C, A, k, Pk, kPresent, kValue;
// 1. Let items be ToObject(arrayLike).
items = Object(arrayLike);
// 3. Let lenValue be the result of calling the [[Get]]
// internal method of items with the argument "length".
// 4. Let len be ToInteger(lenValue).
len = +items.length;
// 6. Let C be the |this| value.
C = this;
// 7. If isConstructor(C) is true, then
if ( isConstructor(C) ) {
// a. Let newObj be the result of calling the
// [[Construct]] internal method of C with an argument
// list containing the single item len.
// b. Let A be ToObject(newObj).
A = Object(new C(len));
} else {
A = new Array(len);
}
// 10. Let k be 0.
k = 0;
// 11. Repeat, while k < len
while ( k < len ) {
// a. Let Pk be ToString(k).
Pk = String(k);
// b. Let kPresent be the result of calling the [[HasProperty]]
// internal method of items with argument Pk.
kPresent = items.hasOwnProperty(Pk);
// c. If kPresent is true, then...
if ( kPresent ) {
// i. Let kValue be the result of calling the [[Get]]
// internal method of items with argument Pk.
kValue = items[ Pk ];
// ii. ReturnIfAbrupt(kValue).
// iii. Let defineStatus be the result of calling the
// [[DefineOwnProperty]] internal method of A with
// arguments Pk, Property Descriptor
// {[[Value]]: kValue.[[value]],
// [[Writable]]: true,
// [[Enumerable]]: true,
// [[Configurable]]: true}, and true.
A[ k ] = kValue;
}
// d. Increase k by 1.
k++;
}
// 14. Return A.
return A;
};
Array.of = function() {
var items, len, C, A, k, Pk, kPresent, kValue;
// X. Let items be ToObject(arrayLike).
items = Object(arguments);
// 1. Let lenValue be the result of calling the [[Get]]
// internal method of items with the argument "length".
// 2. Let len be ToInteger(lenValue).
len = +items.length;
// 3. Let C be the |this| value.
C = this;
// 4. If isConstructor(C) is true, then
if ( isConstructor(C) ) {
// a, b.
A = Object(new C(len));
} else {
// 5. Else, a.
A = new Array(len);
}
// 6. omitted
// 7. Let k be 0.
k = 0;
// 8. Repeat, while k < len
while ( k < len ) {
// a. Let Pk be ToString(k).
Pk = String(k);
// b. Let kValue be the result of calling the [[Get]]
// internal method of items with argument Pk.
kValue = items[ Pk ];
// c. Let defineStatus be the result of calling the
// [[DefineOwnProperty]] internal method of A with
// arguments Pk, Property Descriptor
// {[[Value]]: kValue.[[value]],
// [[Writable]]: true,
// [[Enumerable]]: true,
// [[Configurable]]: true}, and true.
A[ k ] = kValue;
// d. omitted
// e. Increase k by 1.
k++;
}
// 9, 10. omitted
// 11. Return A.
return A;
};
global.Array.from = Array.from;
global.Array.of = Array.of;
})( global );
{
// tests
var arrayLike = { 0: "a", 1: "b", 2: "c", length: 3 };
console.log( Array.from(arrayLike) );
console.log( Array.of(0) );
console.log( Array.of(1, null, undefined, false, 2) );
console.log( Array.of() );
var other = {
from: Array.from,
of: Array.of
};
console.log( other.from(arrayLike) );
console.log( other.of(1, null, undefined, false, 2) );
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment