Как объект Javascript может ссылаться на значения сами по себе?

Давайте скажем, что у меня есть следующий javascript:

var obj = {
 key1 : "it ",
 key2 : key1 + " works!"
};
alert(obj.key2);

Эти ошибки с "ключ1 не определены". Я пробовал

this.key1
this[key1]
obj.key1
obj[key1]
this["key1"]
obj["key1"]

и они никогда не будут определены.

Как я могу получить key2 для ссылки на значение key1?

Ответ 1

Может быть, вы можете подумать об удалении атрибута функции. Я имею в виду что-то вроде этого:

var obj = {
  key1: "it ",
  key2: function() {
    return this.key1 + " works!";
  }
};

alert(obj.key2());

Ответ 2

Это может быть достигнуто с помощью функции-конструктора вместо буквального

var o = new function() {
  this.foo = "it";
  this.bar = this.foo + " works"
}

alert(o.bar)

Ответ 3

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

var key1 = "it";
var obj = {
  key1 : key1,
  key2 : key1 + " works!"
};

Кроме того, это не "объект JSON"; это объект Javascript. JSON - это метод представления объекта со строкой (которая является действительным кодом Javascript).

Ответ 4

Один из вариантов - использовать методы getter/setter.

Например, если вам нужно только прочитать вычисленное значение:

var book  = {}

Object.defineProperties(book,{
    key1: { value: "it", enumerable: true },
    key2: {
        enumerable: true,
        get: function(){
            return this.key1 + " works!";
        }
    }
});

console.log(book.key2); //prints "it works!"

Приведенный выше код, однако, не позволит вам определить другое значение для key2.

Итак, все становится немного сложнее, если вы хотите переопределить значение key2. Это всегда будет рассчитанное значение. Скорее всего, что вы хотите.

Однако, если вы хотите переопределить значение key2, вам понадобится место для кэширования его значения независимо от расчета.

В некотором роде:

var book  = { _key2: " works!" }

Object.defineProperties(book,{
    key1: { value: "it", enumerable: true},
    _key2: { enumerable: false},
    key2: {
        enumerable: true,
        get: function(){
            return this.key1 + this._key2;
        },
        set: function(newValue){
            this._key2 = newValue;
        }
    }
});

console.log(book.key2); //it works!

book.key2 = " doesn't work!";
console.log(book.key2); //it doesn't work!

for(var key in book){
    //prints both key1 and key2, but not _key2
    console.log(key + ":" + book[key]); 
}

Еще одна интересная альтернатива - использовать самоинициализирующий объект:

var obj = ({
  x: "it",
  init: function(){
    this.y = this.x + " works!";
    return this;
  }
}).init();

console.log(obj.y); //it works!

Ответ 5

Поскольку оператор, определяющий obj, не закончил, key1 еще не существует. Рассмотрим это решение:

var obj = { key1: "it" };
obj.key2 = obj.key1 + ' ' + 'works!';
// obj.key2 is now 'it works!'

Ответ 6

Это не объект JSON, а объект Javascript, созданный с помощью литеральной нотации объекта. (JSON - это текстовая нотация для обмена данными (подробнее). Если вы имеете дело с исходным кодом JavaScript и не имеете дело со строкой, вы не имеете дело с JSON.)

Внутри инициализатора объекта нет способа ссылаться на другой ключ инициализируемого объекта, потому что нет способа получить ссылку на создаваемый объект, пока инициализатор не завершится. (Там нет ключевого слова сродни this или что-то для этой ситуации.)

Ответ 7

Вы также можете ссылаться на obj, когда вы находитесь внутри функции, а не this.

var obj = {
    key1: "it",
    key2: function(){return obj.key1 + " works!"}
};
alert(obj.key2());

Ответ 8

Это не JSON. JSON был разработан, чтобы быть простым; позволяя произвольные выражения не просто.

В полном JavaScript, я не думаю, что вы можете сделать это напрямую. Вы не можете ссылаться на this, пока объект с именем obj не будет полностью построен. Итак, вам нужно обходное решение, что кто-то с большим количеством JavaScript-fu, чем я предоставил.