Есть ли способ заставить что-то вроде следующего работать в JavaScript?
var foo = {
a: 5,
b: 6,
c: this.a + this.b // Doesn't work
};
В текущей форме этот код явно выдает ошибку ссылки, поскольку this
не ссылается на foo
. Но есть ли способ иметь значение в свойствах литерала объекта зависит от других свойств ранее заявляли?
javascript
object-literal
kpozin
источник
источник
foo.a
илиfoo.b
изменены, то значениеfoo.c
также будет меняться синхронно. Это может или не может быть то, что требуется.this
связывается с самым глубоким вложенным объектом. Например:... x: { get c () { /*this is x, not foo*/ } } ...
foo
оно объявляется как переменная иc
будет оцениваться только в тот момент, когда оно вызывается, использованиеfoo
insidec
будет работать, в отличие отthis
(будьте осторожны)Вы могли бы сделать что-то вроде:
Это будет своего рода однократная инициализация объекта.
Обратите внимание, что вы фактически присваиваете возвращаемое значение
init()
дляfoo
, поэтому вы должныreturn this
.источник
delete this.init
раньше,return this
так чтоfoo
это не polutedinit()
вызову был непосредственно добавлен литерал, чтобы сохранить его в одном выражении. Но, конечно, вы можете вызывать функцию отдельно от того, что хотите.Очевидный, простой ответ отсутствует, поэтому для полноты:
Нет. Все решения здесь откладывают его до тех пор, пока объект не будет создан (различными способами), а затем присваивают третье свойство. Самый простой способ - просто сделать это:
Все остальные - просто более косвенные способы сделать то же самое. (Феликс особенно умен, но требует создания и уничтожения временной функции, добавления сложности; либо оставляет дополнительное свойство для объекта, либо [если
delete
это свойство] влияет на производительность последующих обращений к этому объекту.)Если вам нужно, чтобы все было в одном выражении, вы можете сделать это без временного свойства:
Или, конечно, если вам нужно сделать это более одного раза:
тогда где вам нужно его использовать:
источник
this
доступен только для методов указанного объекта, но никаких других свойств. Есть идеи, где я могу найти это? Спасибо!delete
на 10% быстрее, а gecko:delete
всего на 1% медленнее.Просто создайте анонимную функцию:
источник
new Point(x, y)
за исключением того, что функция не названа для повторного использования.var foo = function() { this.…; return this; }.call({});
что синтаксически не сильно отличается, но семантически вменяемым.new
ключевое слово.Теперь в ES6 вы можете создавать ленивые кэшированные свойства. При первом использовании свойство оценивается один раз, чтобы стать нормальным статическим свойством. Результат: второй раз, когда математические функции пропускаются.
Магия в добытчике.
В стрелке геттер
this
подхватывает окружающий лексический прицел .источник
Object.defineProperty(foo, 'c', {get:function() {...}})
для их определения. Это легко сделать ненавязчивым способом на такой фабрике, как эта. Конечно, если вы можете использоватьget
сахар, он будет более читабельным, но возможность была там.Некоторое закрытие должно иметь дело с этим;
Все переменные, объявленные внутри,
foo
являются частнымиfoo
, как и следовало ожидать при любом объявлении функции, и поскольку все они находятся в области видимости, все они имеют доступ друг к другу без необходимости ссылатьсяthis
, как вы ожидаете от функции. Разница в том, что эта функция возвращает объект, который предоставляет приватные переменные и назначает этот объектfoo
. В конце вы возвращаете только тот интерфейс, который хотите представить как объект сreturn {}
оператором.Затем функция выполняется в конце,
()
что приводит к оценке всего объекта foo, всех переменных внутри экземпляра и возвращаемого объекта, добавляемого как свойстваfoo()
.источник
Вы могли бы сделать это так
Этот метод оказался полезным для меня, когда мне пришлось ссылаться на объект, для которого функция была первоначально объявлена. Ниже приведен минимальный пример того, как я его использовал:
Определяя себя как объект, который содержит функцию печати, вы позволяете функции ссылаться на этот объект. Это означает, что вам не нужно будет «связывать» функцию печати с объектом, если вам нужно передать его куда-то еще.
Если вы используете вместо этого,
this
как показано нижеЗатем следующий код будет записывать 0, 1, 2, а затем выдаст ошибку
Используя метод self, вы гарантируете, что print всегда будет возвращать один и тот же объект независимо от контекста, в котором выполняется функция. Приведенный выше код будет работать нормально и будет записывать 0, 1, 2 и 3 при использовании собственной версии
createMyObject()
.источник
Для завершения, в ES6 у нас есть классы (поддерживаемые на момент написания этой статьи только в последних браузерах, но доступные в Babel, TypeScript и других транспиляторах)
источник
Вы можете сделать это с помощью шаблона модуля. Как:
С помощью этого шаблона вы можете создать несколько объектов foo в соответствии с вашими потребностями.
http://jsfiddle.net/jPNxY/1/
источник
}();
, она выполнялась бы самостоятельно и возвращала объект, а не функцию. Кроме того,foo.c
это функция, поэтому запись в нее прерывает эту функцию, и при следующем вызове через нееfooObject.c()
произойдет сбой. Может быть, эта скрипка ближе к тому, что вы собираетесь (это также синглтон, не предназначенный для реализации).Есть несколько способов сделать это; это то, что я бы использовал:
источник
просто для размышления - разместите свойства объекта вне временной шкалы:
выше есть и лучшие ответы . Вот как я изменил пример кода, который вы опрашивали.
ОБНОВИТЬ:
источник
var foo = { get a(){return 5}, get b(){return 6}, get c(){return this.a + this.b} }
теперь вы можете просто сделать этоfoo.c
вместоfoo.c()
:) (не стесняйтесь вставлять это в свой ответ, чтобы форматирование было лучше!)Создание новой функции на литерале вашего объекта и вызов конструктора кажется радикальным отходом от исходной проблемы, и в этом нет необходимости.
Вы не можете ссылаться на одноуровневое свойство во время инициализации литерала объекта.
Далее следует простейшее решение для вычисляемых свойств (без кучи, без функций, без конструктора):
источник
Другие ответы, опубликованные здесь, лучше, но вот альтернатива, которая:
init()
или кода вне литерала объектаСамостоятельно выполняющиеся анонимные функции и хранилище окон
Заказ гарантирован (
bar
доbaz
).Конечно, это загрязняет
window
, но я не могу представить, чтобы кто-то писал сценарий, которыйwindow.temp
должен быть настойчивым. Может быть,tempMyApp
если вы параноик.Это также некрасиво, но иногда полезно. Например, когда вы используете API с жесткими условиями инициализации и не чувствуете необходимость рефакторинга, значит, область видимости верна.
И сухо, конечно.
источник
Ключ ко всему этому - ОБЛАСТЬ ПРИМЕНЕНИЯ .
Вам необходимо инкапсулировать «родительский» (родительский объект) свойства, которое вы хотите определить как его собственный экземплярный объект, а затем вы можете делать ссылки на свойства-братья, используя ключевое слово
this
Очень, очень важно помнить, что если вы ссылаетесь
this
без предварительного уведомления, тоthis
будете ссылаться на внешнюю область ... которая будетwindow
объектом.источник
если ваш объект написан как функция, которая возвращает объект, И вы используете объектный атрибут ES6 'методы', то это возможно:
источник
Я использую следующий код в качестве альтернативы, и он работает. И переменная тоже может быть массивом. (@ Фаусто Р.)
источник
Вот аккуратный способ ES6:
Я использую это, чтобы сделать что-то вроде этого:
источник
Как насчет этого решения, это будет работать и с вложенными объектами с массивом
источник
Добавив вариант, так как я не видел этого точного сценария. Если вы не хотите
c
обновлять когдаa
илиb
обновить, то ES6 IIFE работает хорошо.Для моих нужд у меня есть объект, который относится к массиву, который в конечном итоге будет использоваться в цикле, поэтому я хочу вычислить некоторые общие настройки только один раз, поэтому у меня есть следующее:
Так как мне нужно установить свойство для
indexOfSelectedTier
и мне нужно использовать это значение при установкеhasUpperTierSelection
свойства, я сначала вычисляю это значение и передаю его как параметр в IIFE.источник
Другой подход заключается в том, чтобы сначала объявить объект, прежде чем присваивать ему свойства:
При этом вы можете использовать имя переменной объекта для доступа к уже назначенным значениям.
Лучше всего для
config.js
файла.источник
foo
которая указывает на рассматриваемый объект.Это почти идентично ответу @ slicedtoad, но не использует функцию.
источник
Здесь мы использовали выражения класса, чтобы получить литеральный интерфейс вложенного объекта, который нам нужен. ИМХО это следующая лучшая вещь, чтобы иметь возможность ссылаться на свойства объекта во время создания.
Главное, на что нужно обратить внимание, это то, что при использовании этого решения у вас точно такой же интерфейс, какой был бы у литерала объекта. И синтаксис довольно близок к самому литералу объекта (против использования функции и т. Д.).
Сравните следующее
Решение, которое я предложил
Решение, если бы объектных литералов было бы достаточно
Другой пример
Здесь, в этом классе, вы можете комбинировать несколько относительных путей между собой, что невозможно с литералом объекта.
источник
Если вы хотите использовать нативный JS, другие ответы предоставят хорошие решения.
Но если вы готовы писать объекты, ссылающиеся на себя, например:
Я написал библиотеку npm под названием self-referenced-object, которая поддерживает этот синтаксис и возвращает собственный объект.
источник
b
Значение свойства должно быть:${this.a + this.a}
. Во-вторых, но что не менее важно, вы захотите вернуть число, а не строку, используя что-то вродеparseInt
. Последнее и самое главное, когда я попробовал этот пример, он просто не работает, по той же причине, по которой спрашивает OP. Вthis
возвращает неопределенное значение при использовании его собственное описание объекта. @ alex-e-leon