Как задать свойство свойства при создании объекта

#javascript #object #properties #object-notation

#javascript #объект #свойства #object-нотация

Вопрос:

У меня есть объект, и одним из свойств является массив. Я хочу установить новое свойство для этого массива (customProp = 0). Однако я хочу сделать это внутри объявления MyObject.

 myObject = {
  someString: "text",
  someArray: ["one","two"],
    /* What I've Tried */
    someArray: { customProp: 0 } // Overwrites my array with a new object
    someArray["customProp"]: 0 // Invalid syntax
    someArray: customProp: 0 // Also invalid
}
  

Если я не могу создать массив, а затем установить для него свойство, могу ли я сделать это одним махом (опять же, оставаясь в пределах этого объекта)?



У меня есть еще один (небольшой) вопрос: как я могу сослаться на одно из свойств, все еще находящихся внутри объявления. Я хочу установить otherProp = someString, как мне это сделать?

 myObject = {
  someString: "text",
  otherString: someString, // someString is undefined
  otherString: myObject["someString"], // myObject is undefined
  otherString: this["someString"] // Just... undefined
}
  

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

Ответ №1:

К сожалению, ни один из ваших запросов невозможен. Объектные литералы в JavaScript удобны, но имеют недостатки, в основном те, которые вы обнаружили.

Когда вы находитесь внутри объектного литерала, объект еще не совсем существует. Интерпретатор JavaScript не закончил его обработку. Таким образом, внутри литерала, this указывает на объект непосредственно за пределами литерала, и литерал не имеет возможности ссылаться на другие части самого себя.

К счастью, вы можете сделать и то, и другое, что хотите, просто выполнив это после буквального объявления.

 myObject = {
    someString: 'text',
    someArray: ['one', 'two']
};

myObject.someArray.customProp = 0;
myObject.otherString = myObject.someString;
  

Или, если вы хотите, вы можете обернуть все это внутри функции конструктора и создать свой объект с помощью new .

 function MyObject() {
    this.someArray = ['one', 'two'];
    this.someArray.otherProp = 0;
    this.otherString = this.someString = 'text';
}

var myObject = new MyObject();
  

Комментарии:

1. Я понял, что именно поэтому это не работает, спасибо за подтверждение. Конечно, есть способ задать свойство при создании самого объекта. Если нет, я использую один из двух вариантов. (Это было то, что я на самом деле использовал, прежде чем задавать вопрос; я просто надеялся на что-то более компактное)

2. Я думаю, мы все хотели бы иметь возможность делать это. Это особенно верно для ExtJS, который в значительной степени зависит от объектных литералов, и вы постоянно сталкиваетесь с этим :-/

Ответ №2:

Ну, массивы основаны на числах, так что

 someArray["customProp"]: 0
  

не сработало бы. Для работы ключей на основе строк это должен быть объект Javascript {}. И тогда вы могли бы просто сказать

 someArray: {0:"one",1:"two","customProp":0},
  

Что касается вашего второго вопроса: я не думаю, что это возможно. Объект еще не инициализирован, поэтому вы пока не можете прочитать из него…

Комментарии:

1. Не существует такого понятия, как объект JSON benalman.com/news/2010/03/theres-no-such-thing-as-a-json

2. Объект Javascript с синтаксисом JSON, тогда 😉

3. Это литерал объекта. Синтаксис JSON отражает синтаксис объектного литерала. Очень часто неправильно используемый термин.

4. @Williem Вы можете добавлять произвольные свойства к массиву, потому что это объект. Однако обычно это не предназначено таким образом и не будет работать с функциями-прототипами, которые используют его числовые свойства (например, sort). Хотя это распространенная ошибка разработчиков, не знакомых с JS, это действительно «работает».

5. @AutoSponge Итак, внутренне, чем массив отличается от объекта? Просто функции-прототипы, которые могут быть быстрее, потому что они могут принимать некоторые условия (например, цифровые клавиши)?

Ответ №3:

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

 ["one", "two", {customProp: 0}]
  

Комментарии:

1. Я хочу, чтобы оно вело себя точно так же, как стандартный массив. Единственное отличие в том, что мне нужно одно пользовательское свойство (в частности, оно будет запоминать, на какой индекс я ссылаюсь). Я стремлюсь к тому, чтобы это свойство не повторялось с помощью методов прототипа.

2. Тогда вы можете это сделать, но вы не можете ссылаться на массив по имени свойства в другом значении свойства.