Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Array.from and Array.of

Array.from() & Array.of()

Original discussion began on Twitter and can be found by starting here and here. Discussion was continued on es-discuss mailing list in the thread Pure win: Array.from and Array.of

Update Nov. 3, 2011

Official strawman has been posted: http://wiki.ecmascript.org/doku.php?id=strawman:array_extras

Array.from( arg ) [ Unary ]

Converts a single argument that is an array-like object or list (eg. arguments, NodeList, DOMTokenList (used by classList), NamedNodeMap (used by attributes property)) into a new Array() and returns it;

  1. Let O be the result of calling ToObject( arg ).
  2. Let lenValue be the result of calling the [[Get]] internal method of O with the argument "length".
  3. Let len be ToUint32( lenValue ).
  4. Let A be a new array created as if by the expression new Array() where Array is the standard built-in constructor with that name.
  5. Let k be 0.
  6. Repeat, while k < len
    1. Let Pk be ToString( k ).
    2. Let kPresent be the result of calling the [[HasProperty]] internal method of O with argument Pk.
    3. If kPresent is true, then
      1. Let kValue be the result of calling the [[Get]] internal method of O with argument Pk.
      2. Call the [[DefineOwnProperty]] internal method of A with arguments ToString( k ), Property Descriptor {[[Value]]: kValue, [[Writable]]: true, [[Enumerable]]: true, [[Configurable]]: true}, and false.
    4. Increase k by 1.
  7. return A.

Implementation (Conceptual)

Array.from = function( arg ) {

  var O = Object( arg );
  var len = O.length >>> 0;
  var A = new Array();
  var k = 0;

  while( k < len ) {

    var kValue;

    if ( k in O ) {
      kValue = O[ k ];

      A[ k ] = kValue;
    }

    k++;
  }

  return A;
};

Usage

The following use cases are based on the markup in the the attached file domjunk.html.

var divs = document.querySelectorAll("div");

Array.from( divs );
// [ <div class=​"some classes" data-info=​"12">​</div>​, <div data-info=​"10">​</div>​ ]


Array.from( divs ).forEach(function( node ) {
    console.log( node );    
});
// <div class=​"some classes" data-info=​"12">​</div>​
// <div data-info=​"10">​</div>​


Array.from( divs ).filter(function( node ) {
    return !!node.classList.length;
});
// [ <div class="some classes" data-info="12"></div> ]


Array.from( divs ).reduce(function( prev, current ) {
    return ( +prev.dataset.info ) + ( +current.dataset.info );
});
// 22


Array.from( divs[0].classList )
// ["some", "classes"]


// Now shorter then [].foo.call :)
var a = Array;


a.from( divs );
// [ <div class=​"some classes" data-info=​"12">​</div>​, <div data-info=​"10">​</div>​ ]

Array.of() [ Variable Arity ]

Array.of provides a constructor that, unlike Array, does not have the special case for new Array(42), which presets length (and hints to implementations to preallocate) but leaves holes in [0, length ).

The use-case is when you can't write a literal, because you are passing a function-that-constructs as a funarg, and the eventual caller may pass only one number arg, or several args. In that case, Array will not do the right thing in the one-number-arg case. Explanation by Brendan Eich

Implementation (Conceptual)

// Harmony/ES.next rest params
Array.of = function( ...args ) { 
  return args; 
};

// Capable today
Array.of = function() { 
  return Array.prototype.slice.call( arguments ); 
};

Usage

Array.of( 10 );
// [ 10 ]

// Versus the existing behaviour of new Array():

new Array( 10 );
// [ , , , , , , , , , , ]

// Makes sense when you can't use a literal, such this case...
// ES.next http://wiki.ecmascript.org/doku.php?id=harmony:rest_parameters
var o = (function( ArrayCtor, ...rest ) {
  return ArrayCtor( rest );
})( Array, 10 );

// Using Array.of:
var o = (function( Ctor, args ) {
  return Ctor( ...args );
})( Array.of, args );

// Many args...
Array.of( "things", "that", "aren't", "currently", "an", "array" );

// [ "things", "that", "aren't", "currently", "an", "array" ]




// ES-Discuss Thread:
// https://mail.mozilla.org/pipermail/es-discuss/2011-July/015831.html
// Based on discussion originating here:
// http://twitter.com/#!/littlecalculist/status/89848378682392576
// http://twitter.com/#!/littlecalculist/status/89855977838485504
// Array.from( arrayish ) [ Unary ]
// Array.from( arrayLike ) converts any array-like object
// (eg. arguments, NodeList, DOMTokenList) into a new Array() and returns it;
// Implementation
Array.from = function( arg ) {
var O = Object( arg );
var len = O.length >>> 0;
var A = new Array();
var k = 0;
while( k < len ) {
var kValue;
if ( k in O ) {
kValue = O[ k ];
A[ k ] = kValue;
}
k++;
}
return A;
};
// Usage
var divs = document.querySelectorAll("div");
console.log(
Array.from( divs )
);
// see console
Array.from( divs ).forEach(function( node ) {
console.log( node );
});
var filtered = Array.from( divs ).filter(function( node ) {
return !!node.classList.length;
});
console.log( "filtered", filtered );
// filtered [<div class="some classes" data-info="12"></div>]
var reduced = Array.from( divs ).reduce(function( prev, current ) {
return ( +prev.dataset.info ) + ( +current.dataset.info );
});
console.log( "reduced", reduced );
// reduced 22
console.log(
Array.from( divs[0].classList )
);
var a = Array;
console.log(
// Now shorter then [].foo.call :)
a.from( divs )
);
//-------------------------------------------------------------
// Array.of() [ Variable Arity ]
// Array.of provides a constructor that, unlike Array, does not have the special case for new Array(42),
// which presets length (and hints to implementations to preallocate) but leaves holes in [0, length ).
//
// The use-case is when you can't write a literal, because you are passing a function-that-constructs
// as a funarg, and the eventual caller _may_ pass only one number arg, or several args.
// In that case, Array will not do the right thing in the one-number-arg case.
//
// See also: https://mail.mozilla.org/pipermail/es-discuss/2011-July/015841.html
// Implementation
// Harmony/ES.next rest params
Array.of = function( ...args ) {
return args;
};
// Capable today
Array.of = function() {
return Array.prototype.slice.call( arguments );
};
// Usage
Array.of( 10 );
// [ 10 ]
// Versus the existing behaviour of new Array():
new Array( 10 );
// [ , , , , , , , , , , ]
// Makes sense when you can't use a literal, such this case...
// ES.next http://wiki.ecmascript.org/doku.php?id=harmony:rest_parameters
var o = (function( ArrayCtor, ...rest ) {
return ArrayCtor( rest );
})( Array, 10 );
// Other examples:
console.log(
Array.of( "things", "that", "aren't", "currently", "an", "array" )
);
// ["things", "that", "aren't", "currently", "an", "array"]
console.log(
Array.of.apply( null, [ "foo", "bar", "baz" ] )
);
// [ "foo", "bar", "baz" ]
<div class="some classes" data-info="12"></div>
<div data-info="10"></div>
@guillermo
Copy link

guillermo commented Nov 18, 2011

@rwldrn You are right. Too much time developing interfaces for android/ios. Sorry.

@rousan
Copy link

rousan commented Jun 10, 2017

@guillermo

Array.from = function( arg ) {
    arg.__proto__ = [].__proto__;
    return arg;
};

function A() {
    this.length = 2;
    this[0] = "elem1";
    this[1] = "elem2";
}

A.prototype.printLength = function () {
    console.log(this.length);
};

var a = new A();
console.log(a.printLength());
Array.from(a);
console.log(a.printLength()); // TypeError: a.printLength is not a function

[[Prototype]] of arg is changed, it is not a good idea.

@jaydevpatidar
Copy link

jaydevpatidar commented May 4, 2022

how do i convert a object type to array type
have any function to convert object to array

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment