Деструктуризация присваивания в JavaScript
-
03-07-2019 - |
Вопрос
Как можно увидеть в журнале изменений 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}
.Но это можно было бы легко сделать, если бы кто-то хотел такого поведения.
Какое решение лучше?
Решение
Прежде всего, 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 станут более широко доступными.
Другие советы
Вам не нужна фиктивная переменная «_».Вы можете напрямую создавать «глобальные» переменные, используя область объекта окна:
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
Вот что я сделал в PHPstorm 10:
Файл -> Настройки -> Языки и платформы -> ...
...установите языковую версию JavaScript, например.JavaScript 1.8.5...
-> нажмите «Применить».
В стандартном 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/ )