Created
July 27, 2012 07:01
-
-
Save rwaldron/3186576 to your computer and use it in GitHub Desktop.
Correct implementation of Array.from and Array.of as they are currently spec'ed. Includes "isConstructor"
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(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