2016-08-27 4 views
0

Можно ли одновременно присвоить значение нескольким объектам JavaScript?Назначить ключ нескольким объектам

Очевидно, это можно сделать с помощью цикла for и т. Д., Но мне любопытно, есть ли что-то в новой версии языка, что делает это возможным. Подобный синтаксис уже существует на нескольких других языках, я просто не могу найти эквивалент JavaScript.

В идеале, синтаксис будет выглядеть примерно так:

{App1, App2, App3}.foo = "bar" 

App1.foo === "bar" // true 
App2.foo === "bar" // true 
+6

Нет, этого не существует на этом языке. Я не думаю, что мне когда-либо приходилось делать это за пределами массива, поэтому «карта» всегда отлично работала для меня –

+0

Да, это то, что я сейчас использую. Просто любопытно, есть ли вещь ES6/7, которая делает это возможным. – samcorcos

+0

Вы ищете * Объективы * :-) – Bergi

ответ

2

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

set(onList(property("foo")), [App1, App2, App3]); 

Но это уродливое, не так ли? И вы просили новые функции ES6.Да, Proxy может помочь нам сделать это гораздо более красивым, действительно:

ListProxy(App1, App2, App3).foo = "bar"; 

Вот как бы реализовать такую ​​функцию:

const ListProxy = (() => { 
    const handler = { 
    set(target, property, value) { 
     for (const t of target) 
     t[property] = value; 
    }, 
    get(target, property) { 
     if (typeof target == "function") 
     target = target.values; 
     const maybe = target.filter(x => property in Object(x)); 
     if (maybe.length == 0) return undefined; 
     let values = maybe.map(x => x[property]); 
     if (values.every(v => typeof v == "function")) { 
     function fnList(...args) { 
      return maybe.map(v => v[property](...args)); 
     } 
     fnList.values = values; 
     values = fnList; 
     } 
     return new Proxy(values, handler); 
    } 
    }; 
    return function ListProxy(...args) { return new Proxy(args, handler); }; 
})(); 

Метод get не является жизненно важным, но это допускает более глубокие цепочки и даже вызовы функций вместо назначений:

ListProxy({value:"ax"}, {value:"by"}).value[0].toUpperCase(); // ["A","B"] 
-1

Я не думаю, что специальный синтаксис для этого требуется, я бы предпочел назначить его с помощью основной ES6:

const baz = { foo: "bar" };

[App1, App2, App3].forEach(app => app.value = baz);

+0

OP сказал, что он не хочет использовать какие-либо петли. –

+0

@ SoftwareEngineer171: Ваш подход также использует forEach. Но в любом случае это не так (если вы внимательно прочитали вопрос, то искатель заметил, что он прекрасно понимает, что это может быть достигнуто в цикле, но не утверждал, что «он не хочет использовать какие-либо петли») , Я скорее хотел бы указать, насколько коротким, простым и удобочитаемым это достичь этого без какого-либо специального синтаксиса, просто ES6 – Mobiletainment

+0

OP заявила, что хочет использовать синтаксис, аналогичный тому, который он предоставил. Таким образом, использование цикла 'forEach' допускается, если оно используется только один раз при инициализации функции setter. Цель состоит в том, чтобы сделать аналогичный синтаксис, а не показывать ему, как стандартный способ прост. PS - Я не ответил на ваш ответ. –

-1

вы можете использовать:
App1.value = App2.value = {foo: "bar"};
Или
App1.value.foo = App2.value.foo = "bar";

2

Там нет родного способа сделать это. Однако, если вы просто ищете аналогичный синтаксис, вы можете сделать что-то подобное. Вы можете создать прокси-функцию, которая сделает это за вас.

var _ = (...args) => { 
    var proxy = new Proxy(args, { 
     set: (target, property, value) => { 
      target.forEach(object => object[property] = value); 
     } 
    }); 
    return proxy; 
}; 

var App1 = {}, App2 = {}, App3 = {}; 

_(App1, App2, App3).value = { 
    foo: 'bar' 
}; 

_(App1, App2, App3).someOtherValue = { 
    foo: 'baz' 
}; 

console.log(App1); // { value: { foo: 'bar' }, someOtherValue: { foo: 'baz' } } 
console.log(App2); // { value: { foo: 'bar' }, someOtherValue: { foo: 'baz' } } 
console.log(App3); // { value: { foo: 'bar' }, someOtherValue: { foo: 'baz' } } 
+2

Скорее используйте 'Proxy' и в явном переводе массива. Не расширяйте 'Array.prototype'! – Bergi

+0

@ Bergi Согласен, лучше использовать прокси. Я обновил свой ответ. –

+0

Ницца! Я сделал еще один шаг в своем ответе :-) – Bergi

0

Единственный способ сделать что-то вроде синтаксиса вы предлагаете работу, чтобы продлить Object прототип, считает ли не один, что это хорошая идея (это не так).

const App1 = {}, App2 = {}, App3 = {}; 
 

 
Object.defineProperty(Object.prototype, 'values', { 
 
    set(value) { 
 
    for (let prop in this) this[prop].value = value; 
 
    } 
 
}); 
 

 
({App1, App2, App3}).values = "foo"; 
 
console.log(App1.value);

Вы никогда бы не смог написать {App1, App2, App2}.value, потому что анализатор JS интерпретирует ведущую { как начало блока. Следовательно, необходимо заключить его в круглые скобки.

Вы не можете использовать value, чтобы установить все значения, поскольку это противоречило бы свойству value, которое вы хотите установить на отдельные объекты. Следовательно, вместо этого мы используем values.

+1

Да, это действительно не очень хорошая идея. – Bergi

+0

Во-первых, это неправильная практика для изменения собственного прототипа. Во-вторых, он работает только с одним свойством - 'values'. Что делать, если OP хочет изменить другое свойство? –

+0

@ SoftwareEngineer171 Правильно, вот почему я уже сказал в своем ответе, что это не очень хорошая идея. –

Смежные вопросы