Last active
February 12, 2024 00:35
-
-
Save unscriptable/6089437 to your computer and use it in GitHub Desktop.
ES6 WTF Array.from().
We can't do some seemingly simple things with the generic Array.from() as it is specified today.
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
// IIUC, the proposed spec for Array.from at http://people.mozilla.org/~jorendorff/es6-draft.html#sec-15.4.2.4 | |
// is generic, which means the function can be applied to other constructors. Like this, for instance: | |
// | |
// var myString = Array.from.call(String, arrayOfChars); | |
// | |
// It does this by calling the constructor of `this` and passing the length of the argument (arg.length). | |
// I tried shimming it here: https://github.com/cujojs/poly/blob/dev/array-es6.js#L44-L54 | |
// Unfortunately, this yields some interesting results... | |
// Convert an array of bytes or characters to a string: | |
var arrayOfChars = ['f', 'o', 'o']; | |
console.log(Array.from.call(String, arrayOfChars)); | |
// > TypeError: Cannot assign to read only property 'length' of [object String] | |
// If we place a try-catch around the line in the shim that assigns length, we get this: | |
var arrayOfChars = ['f', 'o', 'o']; | |
console.log(Array.from.call(String, arrayOfChars)); | |
// > String {0: "3", 1: "o", 2: "o", 0: "3"} | |
// What is that? It's a `new String('3')` with some integer property turds on it. | |
// Why '3'? Because that's the length of the input, arrayOfChars. | |
// The line of code that constructs the new String passes the length of arrayOfChars, and | |
// the String constructor converts that to a string and uses it as the value. | |
// Sure, we could achieve `Array.from.call(String, arrayOfChars)` by doing this: | |
arrayOfChars.join(''); | |
// but Array.from sure feels like a more direct solution. | |
// So, what if want to create an Array-like object? Maybe something we can use as a "sparse array". | |
// Here's my first inkling about how we could do it. Just use the Object constructor: | |
var someItems = [1, 2, 3]; | |
console.log(Array.from.call(Object, someItems)); | |
// > Number {0: 1, 1: 2, 2: 3, length: 3} | |
// Whaaaaa???? Dang. That's not what I wanted. :( It's a `new Object(3)` with some more integer turds. | |
// Again, this happens because the spec says to pass length of the input to the Object constructor. | |
// Also, `Array.from.call(Object, someItems)` could be done like this: | |
someItems.reduce(function (alo, item, i) { alo[i] = item; return alo; }, { length: someItems.length }); | |
// but `Array.from.call(Object, someItems)` seems so much more elegant. | |
// Can we change the spec to allow generic (and useful) behavior for String and Object, too? | |
// Of course, it's quite possible I'm doing it wrong, too. :) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Array.from
exists to convert thearguments
object into a array. It's more duct tape than a feature.It might be put to use on Set's and Typed Arrays too to justify its existence.