Разрушающее присваивание в JavaScript - PullRequest
16 голосов
/ 15 октября 2008

Как видно из журнала изменений Mozilla для JavaScript 1.7, в них добавлено назначение деструктуризации. К сожалению, я не очень люблю синтаксис (зачем писать a и b дважды?):

var a, b;  
[a, b] = f();

Что-то вроде этого было бы намного лучше:

var [a, b] = f();

Это все равно будет обратно совместимо. Подобная Python деструктуризация не будет обратно совместимой.

В любом случае, лучшее решение для JavaScript 1.5, которое мне удалось придумать, это:

function assign(array, map) {
    var o = Object();
    var i = 0;
    $.each(map, function(e, _) {
        o[e] = array[i++];
    });
    return o;
}

Который работает как:

var array = [1,2];
var _ = assign[array, { var1: null, var2: null });
_.var1; // prints 1
_.var2; // prints 2

Но это действительно отстой, потому что _ не имеет смысла. Это просто пустая оболочка для хранения имен. Но, к сожалению, это нужно, потому что в JavaScript нет указателей. С положительной стороны вы можете назначить значения по умолчанию в случае, если значения не совпадают. Также обратите внимание, что это решение не пытается нарезать массив. Так что вы не можете сделать что-то вроде {first: 0, rest: 0}. Но это легко сделать, если кто-то хочет такого поведения.

Какое решение лучше?

Ответы [ 4 ]

23 голосов
/ 16 октября 2008

Во-первых, var [a, b] = f() прекрасно работает в JavaScript 1.7 - попробуйте!

Во-вторых, вы можете сгладить синтаксис использования слегка , используя with():

var array = [1,2];
with (assign(array, { var1: null, var2: null }))
{
   var1; // == 1
   var2; // == 2
}

Конечно, это не позволит вам изменять значения существующих переменных, поэтому ИМХО это намного менее полезно, чем функция JavaScript 1.7. В коде, который я пишу , теперь , я просто возвращаю объекты напрямую и ссылаюсь на их члены - я буду ждать, пока функции 1.7 станут более доступными.

4 голосов
/ 15 октября 2008

Вам не нужна фиктивная переменная "_". Вы можете напрямую создавать «глобальные» переменные, используя область объекта окна:

window["foo"] = "bar";
alert(foo); // Gives "bar"

Вот еще несколько моментов:

  • Я бы не назвал эту функцию «назначить», потому что это слишком общий срок.
  • Чтобы больше походить на JS 1.7 Синтаксис, я бы заставил функцию принять пункт назначения в качестве первого аргумент и источник как Второй аргумент.
  • Использование литерала объекта для передачи переменных назначения - это круто, но его можно спутать с деструктуризацией JS 1.7, где целью является фактически объект, а не массив. Я предпочитаю просто использовать разделенный запятыми список имен переменных в виде строки.

Вот что я придумал:

function destructure(dest, src) {  
    dest = dest.split(",");  

    for (var i = 0; i < src.length; i++) {  
        window[dest[i]] = src[i];  
    }  
}  

var arr = [42, 66];  

destructure("var1,var2", arr); 

alert(var1); // Gives 42
alert(var2); // Gives 66
1 голос
/ 22 декабря 2015

Вот что я сделал в PHPstorm 10:

Файл -> Настройки -> Языки и рамки -> ...

... установить версию языка JavaScript, например, на JavaScript 1.8.5 ...

-> нажмите Применить.

0 голосов
/ 14 сентября 2013

В стандартном JavaScript мы привыкаем ко всем видам безобразия, и эмуляция назначения деструктуры с использованием промежуточной переменной не так уж и плоха:

function divMod1(a, b) {
    return [ Math.floor(a / b), a % b ];
}

var _ = divMod1(11, 3);
var div = _[0];
var mod = _[1];
alert("(1) div=" + div + ", mod=" + mod );

Тем не менее, я думаю, что следующая картина более логична:

function divMod2(a, b, callback) {
    callback(Math.floor(a / b), a % b);
}

divMod2(11, 3, function(div, mod) {
    alert("(2) div=" + div + ", mod=" + mod );
});

Обратите внимание, что вместо возврата двух результатов в виде массива мы передаем их в качестве аргументов функции обратного вызова.

(см. Код, работающий на http://jsfiddle.net/vVQE3/)

...