71

Really like that function.

$matches = array('12', 'watt');
list($value, $unit) = $matches;

Is there a Javascript equivalent of that?

Brett Zamir
  • 14,034
  • 6
  • 54
  • 77
Markus Hedlund
  • 23,374
  • 22
  • 80
  • 109

9 Answers9

62

There is, in 'newer' versions of Javascript: Destructuring assignment - Javascript 1.7. It's probably only supported in Mozilla-based browsers, and maybe in Rhino.

var a = 1;  
var b = 3;  

[a, b] = [b, a];  

EDIT: actually it wouldn't surprise me if the V8 Javascript library (and thus Chrome) supports this. But don't count on it either Now supported in all modern browsers(except IE, of course).

ashleedawg
  • 20,365
  • 9
  • 72
  • 105
Nicolás
  • 7,423
  • 33
  • 35
  • 6
    Neat! I really like all the cool stuff they've put into the new versions of Javascript! Just feels like we wont be able to use them for ages.. – Markus Hedlund Dec 23 '09 at 18:38
  • 1
    Year 2015 and still unsupported by V8. –  Mar 05 '15 at 19:21
  • 1
    Firefox supports it since version 2 back in 2006. It's still not supported by V8/Chrome in 2015. Chrome is the new IE. – cronvel Aug 19 '15 at 13:58
  • Be careful using this still in 2018; IE never supported it, and many people still use it. Useful for judging compatibility: http://kangax.github.io/compat-table/es6/ – Autumn Leonard Nov 16 '18 at 21:44
  • Reporting from 2019 March. This is working in Chrome 72 (64-bit). – akinuri Mar 15 '19 at 08:01
20

try this:

matches = ['12', 'watt'];
[value, unit] = matches; 
The Mask
  • 17,007
  • 37
  • 111
  • 185
19

ES6 does support this directly now via array destructuring.

const matches = ['12', 'watt'];
const [value, unit] = matches;
Ben Fortune
  • 31,623
  • 10
  • 79
  • 80
  • 2
    As of mid-2019 this is the best answer. The accepted answer will throw "[variable] is not defined (no-undef)" warnings in many linters. This corrects for that. Note that you can also do array deconstructing in for...of loops – Tyler V. Jun 07 '19 at 05:39
4

This is my solution for using List/Explode on Javascript. Fiddle Working Example

First the implementation :

var dateMonth = "04/15";
dateMonth.split("/").list("month","day", "year");
month == "04";
day == "15";
year == null;

It also allows for scoping the new generated variables :

var scoped = (function()
{ 
    var dateMonth = "07/24/2013"; 
    dateMonth.split("/").list("month","day", "year", this);
    this.month == "07";
    this.day == "24";
    this.year == "2013";
})();

This was accomplished by modifying an the Array prototype.

Array.prototype.list = function()
{
    var 
        limit = this.length,
        orphans = arguments.length - limit,
        scope = orphans > 0  && typeof(arguments[arguments.length-1]) != "string" ? arguments[arguments.length-1] : window 
    ;

    while(limit--) scope[arguments[limit]] = this[limit];

    if(scope != window) orphans--;

    if(orphans > 0)
    {
        orphans += this.length;
        while(orphans-- > this.length) scope[arguments[orphans]] = null;  
    }  
}
lac_dev
  • 1,336
  • 14
  • 20
  • I'm sticking with my solution. If you try something like : matches = ['12', 'watt']; [value, unit] = matches; Or function () { var [year, month] = $(this).val().split("/"); In Chrome, it will throw an error : "ReferenceError: Invalid left-hand side in assignment" – lac_dev Jul 24 '13 at 18:51
  • Using `window` as a default object is a very bad idea. – Bergi Feb 20 '15 at 00:17
  • @Bergi he only defaults to it. You can provide an object as the last parameter and it will use that. – micahblu Dec 10 '15 at 20:10
  • @lac_dev love this little script, works perfectly for me. Very nice that you account for labels that exceed the data – micahblu Dec 10 '15 at 20:21
2

CoffeeScript offers destructuring assignment with the syntax:

[a, b] = someFunctionReturningAnArray()

This is pretty much identical to the feature offered in very new JavaScript versions. However, CoffeeScript produces compiled JS that is compatible even with IE6's JavaScript engine, and therefore it's a good option if compatibility is vital.

00dani
  • 1,498
  • 15
  • 17
2

There is a experimental implementation of list() by PHPJS here:
https://github.com/kvz/phpjs/blob/master/_experimental/array/list.js

powtac
  • 40,542
  • 28
  • 115
  • 170
  • The second link in this post is dead (*404 - This is not the web page you are looking for*). – Pang Jan 25 '17 at 09:20
1

Since most JavaScript implementations don't yet support that feature, you could simply do it in a more JavaScript-like fashion:

function list(){
    var args = arguments;
    return function(array){
        var obj = {};
        for(i=0; i<args.length; i++){
            obj[args[i]] = array[i];
        }
        return obj;
    };
}

Example:

var array = ['GET', '/users', 'UserController'];
var obj = {};

obj = list('method', 'route', 'controller')(array);

console.log(obj.method);        // "GET"
console.log(obj.route);         // "/users"
console.log(obj.controller);    // "UserController"

Check the fiddle


An alternative is to add a list-method to Array.prototype (even I wouldn't recommend it):

Array.prototype.list = function(){
    var i, obj = {};
    for(i=0; i<arguments.length; i++){
        obj[arguments[i]] = this[i];
    }
    // if you do this, you pass to the dark side `,:,´
    this.props = obj;
    return obj;
};

Example:

/**
 * Example 1: use Array.prototype.props
 */

var array = ['GET', '/users', 'UserController'];
array.list('method', 'route', 'controller');

console.log(array.props.method);        // "GET"
console.log(array.props.route);         // "/users"
console.log(array.props.controller);    // "UserController"

/**
 * Example 2: use the return value
 */

var array = ['GET', '/users', 'UserController'];
var props = array.list('method', 'route', 'controller');

console.log(props.method);      // "GET"
console.log(props.route);       // "/users"
console.log(props.controller);  // "UserController"

Check the fiddle for that one

rcd
  • 4,250
  • 1
  • 22
  • 23
0

This is my hack at it; as short as I could get it without writing a function to do it. Gotta be careful of the scope of "this" though:

list = ["a","b","c"];
vals = [1,2,3];
for(var i in vals)this[list[i]]=vals[i];
console.log(a,b,c);

Good enough for a laugh. I still assign each variable one at a time:

a=vals[0];
b=vals[1];
c=vals[2];

It's much shorter this way. Besides, if you've got a bunch of variables they should probably be kept in the array, or even better they should be properties of a closure, instead of declaring them all separately.

i_a
  • 2,735
  • 1
  • 22
  • 21
-2
function list(fn,array){
    if(fn.length && array.length){
        for(var i=0;i<array.length;i++){
            var applyArray = [];
            for(var j=0;j<array[i].length;j++){
                fn[j] = array[i][j];
                applyArray.push(fn[j]);
            }
        fn.apply(this,applyArray);
       }
   }
}

Example:

//array array mixture for composure
var arrayMixture = [ ["coffee","sugar","milk"], ["tea","sugar","honey"] ];
//call our function


list(function(treat,addin,addin2){
    console.log("I like "+treat+" with " + addin + " and " + addin2);
},arrayMixture);


//output:
//I like coffee with sugar and milk
//I like tea with sugar and honey
EasyBB
  • 6,176
  • 9
  • 47
  • 77