Как деструктурировать все свойства в текущую область/закрытие в ES2015?

Я хотел бы сделать что-то вроде этого:

const vegetableColors = {corn: 'yellow', peas: 'green'};

const {*} = vegetableColors;

console.log(corn);// yellow
console.log(peas);// green

Кажется, я не могу найти или понять, как это сделать, но я действительно думал, что видел это где-то раньше! :П

ПРИМЕЧАНИЕ. я использую Babel с stage, установленным на 0;

КОНТЕКСТ: я стараюсь быть более сухим в JSX и не ссылаться на this.state или this.props везде. А также не нужно постоянно добавлять свойства для деструктуризации при изменении данных.


person Resist Design    schedule 09.08.2015    source источник
comment
Пожалуйста, попробуйте найти, где вы видели это раньше, я хотел бы прочитать эту статью   -  person Bergi    schedule 09.08.2015
comment
Допустим, вы могли бы это сделать. Итак, каким будет следующее утверждение? Как бы вы написали код, который использовал бы переменные, появившиеся из такого объявления, если бы вы не знали заранее, каковы их имена?   -  person Pointy    schedule 09.08.2015
comment
@Pointy, дело в том, что если вы используете служебную библиотеку, такую ​​​​как подчеркивание или ramda, вам не нужно постоянно возвращаться к началу вашего файла и редактировать строку, в которой вы импортируете свои функции по имени каждый раз, когда вы используете новый (или добавляйте _. или R. к каждому вызову функции).   -  person Jonah    schedule 30.05.2016
comment
@ Джона, это звучит как серьезный запах кода. Загрязнение вашего пространства имен волей-неволей кажется рецептом постоянной потенциальной катастрофы.   -  person Pointy    schedule 30.05.2016
comment
@Pointy, вы говорите, что невозможно оказаться в ситуации, когда вы знакомы с какой-то служебной библиотекой и просто хотите использовать ее функции? Что, если вы написали библиотеку? В чем именно заключается эта потенциальная катастрофа? Что вы забыли, что в библиотеке есть функция под названием X?   -  person Jonah    schedule 30.05.2016
comment
Я не говорю, что в такой ситуации быть невозможно. Я говорю, что это ситуация, которую нужно изо всех сил избегать. Необнаруживаемые конфликты имен — это рецепт действительно плохого дня.   -  person Pointy    schedule 30.05.2016
comment
В современном мире менеджеров пакетов и автоматизированных систем обновления это может стать реальной проблемой. Обратите внимание, что n.x точечные выпуски могут свободно добавлять API в пакет, если они не нарушают работу старых API. Добавление чего-либо в API может полностью включать в себя добавление совершенно новых функций. Итак, вы делаете npm update, и вдруг (или, что еще хуже, не вдруг) ваши вещи перестают работать.   -  person Pointy    schedule 30.05.2016
comment
Вопрос об обновлениях пакетов справедлив.   -  person Jonah    schedule 30.05.2016


Ответы (3)


Я думаю, вы ищете with заявление, он делает именно то, что вы просите:

const vegetableColors = {corn: 'yellow', peas: 'green'};
with (vegetableColors) {
    console.log(corn);// yellow
    console.log(peas);// green
}

Однако он устарел (в строгом режиме, который включает модули ES6) по уважительной причине.

деструктурировать все свойства в текущую область

Вы не можете в ES61. И это хорошо. Будьте точны в отношении переменных, которые вы вводите:

const {corn, peas} = vegetableColors;

В качестве альтернативы вы можете расширить глобальный объект с помощью Object.assign(global, vegetableColors), чтобы поместить их в глобальную область, но на самом деле это хуже, чем оператор with.

1: … и хотя я не знаю, есть ли проект, разрешающий такие вещи в ES7, я могу сказать вам, что любое предложение будет отвергнуто TC :-)

person Bergi    schedule 09.08.2015
comment
На самом деле я только вспомнил свой старый ответ и не сразу подумал о this :-) - person Bergi; 09.08.2015
comment
Я знал о with и никогда бы не воспользовался этим, но это именно то, о чем я прошу... Дерьмо! О чем я только думал!? :П - person Resist Design; 09.08.2015
comment
Я не согласен, что это хорошо. Конечно, это может быть опасным. Это также может быть именно то, что хочет сделать программист. Он должен иметь возможность сделать выбор сам. И дело не в том, что javascript как язык занял жесткую позицию по дизайну против всего, что позволяет вам выстрелить себе в ногу. - person Jonah; 30.05.2016
comment
@Jonah: Строгий режим является конструктивной позицией против функций стрельбы по ногам и предотвращения оптимизации :-) Вы все еще можете использовать with, если хотите, он не будет удален из языка (в основном для обратного - проблемы с совместимостью, хотя). - person Bergi; 30.05.2016
comment
Эх, я все еще думаю, что это была бы полезная функция, но я вижу другую сторону аргумента. В любом случае, with не является решением imo, потому что теперь вам нужно обернуть весь модуль в with и добавить отступ уровня, что даже хуже, чем добавлять имя объекта перед каждым вызовом функции или импортировать все по имени вверху с помощью деструктурирование. - person Jonah; 30.05.2016
comment
@Jonah: Вы можете удалить отступ, закрывающий модуль, если хотите, особенно если это вложенные операторы with. Или перепишите некоторый пользовательский синтаксис импорта в оператор with как часть шага сборки, если вы его вообще не видите. Однако на самом деле отступ может служить напоминанием о том, что вы находитесь в небезопасной области. - person Bergi; 30.05.2016
comment
Ну, если я достаточно забочусь об этом, чтобы использовать шаг сборки, я думаю, что лучше просто автоматически сгенерировать оператор импорта деструктурирования объекта на основе используемых функций и требуемых объектов. Это было бы не слишком сложно. Но, думаю, меня это мало волнует :) - person Jonah; 30.05.2016

Я думаю, вы ищете:

const {corn, peas} = vegetableColors;

Жить на REPL Babel


Если Пойнти прав что вы спрашиваете, как это сделать, не зная имен corn и peas, вы не можете с помощью деструктурирующего присваивания.

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

// I'm sure you don't really want this, just being thorough
Object.keys(vegetableColors).forEach((key) => {
    Object.defineProperty(this, key, {
        value: vegetableColors[key]
    });
});

(Вставьте туда enumerable: true, если вы хотите, чтобы эти псевдоконстанты были перечисляемыми.)

Это работает в глобальной области видимости, потому что this относится к глобальному объекту.

person T.J. Crowder    schedule 09.08.2015
comment
Я думаю, что ищет OP, - это способ распаковать свойства объекта в локальные переменные с одинаковыми именами без какого-либо предварительного знания исходного объекта. (Я не могу представить, какая от этого польза.) - person Pointy; 09.08.2015
comment
@Pointy: я добавил контекст к вопросу только для вас :) - person Resist Design; 09.08.2015
comment
Или, может быть, вы хотите распаковать 100 свойств, не называя их все явным образом и не обновляя список каждый раз, когда к объекту добавляется новое свойство. - person Moss; 01.05.2020

Я бы не рекомендовал это, но вы можете использовать eval() для выполнения чего-то подобного:

vegetableColors = {corn: 'yellow', peas: 'green'};

function test() {
    for ( let i=0; i < Object.keys(vegetableColors).length; i++ ) {
        let k = Object.keys(vegetableColors)[i];
        eval(`var ${k} = vegetableColors['${k}']`);
    }

    console.log(corn); // yellow
}

test();

console.log(corn); // undefined (out of scope)
person kmoser    schedule 16.11.2020