#javascript
Объясните как работает алгоритм деструктурирующего присваивания. Я решил проверить поведение, но не могу понять, почему консоль выдает именно такие результаты. Прежде чем задавать вопрос, я ознакомлялся со всеми источниками, кроме самой спецификации, ибо она сложная для восприятия, и я не знаю английский. Источники: ES6: Реструктуризующее присваивание, Деструктуризация, Деструктурирующее присваивание. 1 var {a,aa,...aaa} = [2, 4, 23]; console.log(a, aa, aaa); 2 var [a,aa,...aaa] = {a:2, aa: 4, aaa: 23}; console.log(a, aa, aaa); UPD: Воспользовался Babel.js, может он как - то поможет.
Ответы
Ответ 1
var {a,aa,...aaa} = [2, 4, 23]; var src = [2, 4, 23]; var a, aa, aaa; a = src.a; aa = src.aa; aaa = {}; for (var key in src) if (key !== 'a' && key !== 'aa' && src.hasOwnProperty(key)) aaa[key] = src[key]; console.log(a, aa, aaa); В таком поведении можно убедиться следующим образом: var {a, b, ...rest} = { __proto__: { b: 2, // декомпозиция в переменную d: 4 // исчезает, т. е. НЕ попадает в rest }, a: 1, // декомпозиция в переменную c: 3 // попадает в rest } console.log(a, b, rest) Если хочется потрошить массив как объект, то можно использовать декомпозицию с переименованием - ведь числа не могут быть иментами переменных, но обращаю внимание, что в aaa всё равно объект, а не массив: var { 0:a, 1:aa, ...aaa } = [2, 4, 23]; console.log(a, aa, aaa); var [a,aa,...aaa] = {a:2, aa: 4, aaa: 23}; var src = {a:2, aa: 4, aaa: 23}; var a, aa, aaa; var i = 0; aaa = []; for (var x of src) { // Упадёт прямо на of switch (i++) { case 0: a = x; break; case 1: aa = x; break; default: aaa.push(x); } } console.log(a, aa, aaa); Через [] можно деструктуризировать только итерируемые объекты: var src = { *[Symbol.iterator]() { yield 2; yield 4; yield 23; } }; var a, aa, aaa; var i = 0; aaa = []; for (var x of src) { switch (i++) { case 0: a = x; break; case 1: aa = x; break; default: aaa.push(x); } } console.log(a, aa, aaa); PS: А вообще лучше всё делать по-человечески: var [a, aa, ...aaa] = [2, 4, 23]; console.log(a, aa, aaa); var {a, aa, ...aaa} = {a:2, aa: 4, aaa: 23}; console.log(a, aa, aaa);Ответ 2
В обоих случаях поведение непонятное так как вы объект пытаетесь пропихнуть в массив и наоборот. В документации смотрим синтаксис: var a, b, rest; [a, b] = [1, 2]; console.log(a); // 1 console.log(b); // 2 [a, b, ...rest] = [1, 2, 3, 4, 5]; console.log(a); // 1 console.log(b); // 2 console.log(rest); // [3, 4, 5] ({a, b} = {a:1, b:2}); console.log(a); // 1 console.log(b); // 2 ({a, b, ...rest} = {a:1, b:2, c:3, d:4}); Тут нету варианта деструктуризации массива в объект и наоборот. Справа и слева во всех примерах одинаковые скобочки, то есть массив деструктурируется в массив, а объект в объект. Вот конструкция которая работает как и предполагается, обратите снимание на скобочки: var [a,aa,...aaa] = [2, 4, 23, 144]; console.log(a, aa, aaa); Пункт 1. Запускаем babel и получаем код: var _ref = [2, 4, 23], a = _ref.a, aa = _ref.aa, aaa = _objectWithoutProperties(_ref, ["a", "aa"]); В a мы кладём ref.a так как _ref это массив то ref.a не задан. Тоже самое с aa. Теперь смотрим aaa,в него мы кладём все значения кроме a и aa, но так как a и aa не заданы, то на выходе получаем все три значения. Подводим итог, в a и aa ничего не кладётся, так как справа у массива нету переменной с названием a и aa, а в aaa мы кладём всё что осталось.Ответ 3
Я, прочитав даже одну статью на MDN, понял суть. Для массивов: Не важно, как был получен массив(многих запутают переменни и функции в примерах на MDN), вся суть в то, что присваивание происходит в том же порядке, что переменные в первом массиве: var [a, b, c]=[vl1,vl2,vl3] a->vl1 b->vl2 c->vl3 Если в правом массиве больше значений, чем в левом, то лишние просто не используются, либо помещаются в переменную с оператором spread (...) var [a, b, c, ...d]=[vl1,vl2,vl3,vl4,vl5] a->vl1 b->vl2 c->vl3 d->[vl4,vl5] Для объектов: Практически тоже самое, только значение помещается в переменные по ключам свойств: var {a,c,b}={a:1,b:2,c:3} a->1 b->2 c->3 var {a,c,b,...w}={a:1,b:2,c:3,d:10,e:12} a->1 b->2 c->3 w->{d:10,e:12} В обоих случаях лишние переменные в левом массиве будут объявлены со значением undefined