Двойные квадратные скобки javascript

Объекты

Как мы знаем из главы Типы данных, в JavaScript существует 8 типов данных. Семь из них называются «примитивными», так как содержат только одно значение (будь то строка, число или что-то другое).

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

Объект может быть создан с помощью фигурных скобок с необязательным списком свойств. Свойство – это пара «ключ: значение», где ключ – это строка (также называемая «именем свойства»), а значение может быть чем угодно.

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

Пустой объект («пустой ящик») можно создать, используя один из двух вариантов синтаксиса:

let user = new Object(); // синтаксис "конструктор объекта" let user = <>; // синтаксис "литерал объекта"

Обычно используют вариант с фигурными скобками <. >. Такое объявление называют литералом объекта или литеральной нотацией.

Литералы и свойства

При использовании литерального синтаксиса <. >мы сразу можем поместить в объект несколько свойств в виде пар «ключ: значение»:

У каждого свойства есть ключ (также называемый «имя» или «идентификатор»). После имени свойства следует двоеточие «:» , и затем указывается значение свойства. Если в объекте несколько свойств, то они перечисляются через запятую.

Читайте также:  Php value to bool

В объекте user сейчас находятся два свойства:

  1. Первое свойство с именем «name» и значением «John» .
  2. Второе свойство с именем «age» и значением 30 .

Можно сказать, что наш объект user – это ящик с двумя папками, подписанными «name» и «age».

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

Для обращения к свойствам используется запись «через точку»:

// получаем свойства объекта: alert( user.name ); // John alert( user.age ); // 30

Значение может быть любого типа. Давайте добавим свойство с логическим значением:

Для удаления свойства мы можем использовать оператор delete :

Имя свойства может состоять из нескольких слов, но тогда оно должно быть заключено в кавычки:

Последнее свойство объекта может заканчиваться запятой:

Это называется «висячая запятая». Такой подход упрощает добавление, удаление и перемещение свойств, так как все строки объекта становятся одинаковыми.

Объект, объявленный через const , может быть изменён.

const user = < name: "John" >; user.name = "Pete"; // (*) alert(user.name); // Pete

Может показаться, что строка (*) должна вызвать ошибку, но нет, здесь всё в порядке. Дело в том, что объявление const защищает от изменений только саму переменную user , а не её содержимое.

Определение const выдаст ошибку только если мы присвоим переменной другое значение: user=. .

Есть ещё один способ сделать константами свойства объекта, который мы рассмотрим в главе Флаги и дескрипторы свойств.

Квадратные скобки

Для свойств, имена которых состоят из нескольких слов, доступ к значению «через точку» не работает:

// это вызовет синтаксическую ошибку user.likes birds = true

JavaScript видит, что мы обращаемся к свойству user.likes , а затем идёт непонятное слово birds . В итоге синтаксическая ошибка.

Точка требует, чтобы ключ был именован по правилам именования переменных. То есть не имел пробелов, не начинался с цифры и не содержал специальные символы, кроме $ и _ .

Для таких случаев существует альтернативный способ доступа к свойствам через квадратные скобки. Такой способ сработает с любым именем свойства:

let user = <>; // присваивание значения свойству user["likes birds"] = true; // получение значения свойства alert(user["likes birds"]); // true // удаление свойства delete user["likes birds"];

Сейчас всё в порядке. Обратите внимание, что строка в квадратных скобках заключена в кавычки (подойдёт любой тип кавычек).

Квадратные скобки также позволяют обратиться к свойству, имя которого может быть результатом выражения. Например, имя свойства может храниться в переменной:

let key = "likes birds"; // то же самое, что и user["likes birds"] = true; userДвойные квадратные скобки javascript = true;

Здесь переменная key может быть вычислена во время выполнения кода или зависеть от пользовательского ввода. После этого мы используем её для доступа к свойству. Это даёт нам большую гибкость.

let user = < name: "John", age: 30 >; let key = prompt("Что вы хотите узнать о пользователе?", "name"); // доступ к свойству через переменную alert( userДвойные квадратные скобки javascript ); // John (если ввели "name")

Запись «через точку» такого не позволяет:

let user = < name: "John", age: 30 >; let key = "name"; alert( user.key ); // undefined

Вычисляемые свойства

Мы можем использовать квадратные скобки в литеральной нотации для создания вычисляемого свойства.

let fruit = prompt("Какой фрукт купить?", "apple"); let bag = < [fruit]: 5, // имя свойства будет взято из переменной fruit >; alert( bag.apple ); // 5, если fruit="apple"

Смысл вычисляемого свойства прост: запись [fruit] означает, что имя свойства необходимо взять из переменной fruit .

И если посетитель введёт слово «apple» , то в объекте bag теперь будет лежать свойство .

По сути, пример выше работает так же, как и следующий пример:

let fruit = prompt("Какой фрукт купить?", "apple"); let bag = <>; // имя свойства будет взято из переменной fruit bag[fruit] = 5;

…Но первый пример выглядит лаконичнее.

Мы можем использовать и более сложные выражения в квадратных скобках:

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

Подведём итог: в большинстве случаев, когда имена свойств известны и просты, используется запись через точку. Если же нам нужно что-то более сложное, то мы используем квадратные скобки.

Свойство из переменной

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

function makeUser(name, age) < return < name: name, age: age // . другие свойства >; > let user = makeUser("John", 30); alert(user.name); // John

В примере выше название свойств name и age совпадают с названиями переменных, которые мы подставляем в качестве значений этих свойств. Такой подход настолько распространён, что существуют специальные короткие свойства для упрощения этой записи.

Вместо name:name мы можем написать просто name :

function makeUser(name, age) < return < name, // то же самое, что и name: name age // то же самое, что и age: age // . >; >

Мы можем использовать как обычные свойства, так и короткие в одном и том же объекте:

Ограничения на имена свойств

Как мы уже знаем, имя переменной не может совпадать с зарезервированными словами, такими как «for», «let», «return» и т.д.

Но для свойств объекта такого ограничения нет:

// эти имена свойств допустимы let obj = < for: 1, let: 2, return: 3 >; alert( obj.for + obj.let + obj.return ); // 6

Иными словами, нет никаких ограничений к именам свойств. Они могут быть в виде строк или символов (специальный тип для идентификаторов, который будет рассмотрен позже).

Все другие типы данных будут автоматически преобразованы к строке.

Например, если использовать число 0 в качестве ключа, то оно превратится в строку «0» :

let obj = < 0: "Тест" // то же самое что и "0": "Тест" >; // обе функции alert выведут одно и то же свойство (число 0 преобразуется в строку "0") alert( obj["0"] ); // Тест alert( obj[0] ); // Тест (то же свойство)

Есть небольшой подводный камень, связанный со специальным свойством __proto__ . Мы не можем установить его в необъектное значение:

let obj = <>; obj.__proto__ = 5; // присвоим число alert(obj.__proto__); // [object Object], значение - это объект, т.е. не то, что мы ожидали

Как мы видим, присвоение примитивного значения 5 игнорируется.

Мы более подробно исследуем особенности свойства __proto__ в следующих главах Прототипное наследование, а также предложим способы исправления такого поведения.

Проверка существования свойства, оператор «in»

В отличие от многих других языков, особенность JavaScript-объектов в том, что можно получить доступ к любому свойству. Даже если свойства не существует – ошибки не будет!

При обращении к свойству, которого нет, возвращается undefined . Это позволяет просто проверить существование свойства:

let user = <>; alert( user.noSuchProperty === undefined ); // true означает "свойства нет"

Также существует специальный оператор «in» для проверки существования свойства в объекте.

Источник

ситуация

У меня есть следующая функция, которая использует Promise.

var getDefinitions = function() < return new Promise(function(resolve) < resolve(ContactManager.request("definition:entities")); >); > var definitions = getDefinitions() 

Доступ к свойству PromiseValue напрямую возвращает неопределенное

var value = definitions.PromiseValue; // undefined 

Вопрос

Что означают двойные скобки [[ ]] и как получить значение [[PromiseValue]] .

ОТВЕТЫ

Ответ 1

Что внутри [[]]

Мой вопрос в том, что означают двойные скобки [[]] и как я могу получить значение [[PromiseValue]].

Это внутреннее свойство. Вы не можете получить к нему доступ напрямую. Родной promises может быть развернут только в then с promises или асинхронно в целом — см. Как вернуть ответ от асинхронного вызова. Цитирование спецификации:

Они определяются этой спецификацией исключительно для пояснительных целей. Реализация ECMAScript должна вести себя так, как если бы она создавалась и управлялась внутренними свойствами описанным здесь способом. Имена внутренних свойств заключены в двойные квадратные скобки [[]]. Когда алгоритм использует внутреннее свойство объекта, и объект не реализует указанное внутреннее свойство, генерируется исключение TypeError.

Серьезно, хотя — что это?

Очень приятно! В приведенной выше цитате говорится, что они просто используются в спецификации — поэтому нет причин для их появления на консоли.

Не говорите никому, но это действительно личные символы. Причина, по которой они существуют, заключается в том, что другие внутренние методы могут иметь доступ к [[PromiseValue]] . Например, когда io.js решает вернуть promises вместо принятия обратных вызовов — это позволит ему быстро получить доступ к этим свойствам в тех случаях, когда это гарантировано. Они не подвергаются воздействию снаружи.

Могу ли я получить к ним доступ?

Нет, если вы не создадите собственную версию Chrome или V8. Возможно, в ES7 с модификаторами доступа прямо сейчас нет способа, поскольку они не являются частью спецификации и будут разбиваться на браузеры — извините.

Итак, я получаю мою ценность?

getDefinitions().then(function(defs)< //access them here >); 

Хотя, если бы мне пришлось угадать — вы не должны правильно преобразовывать API, чтобы начать с, поскольку это преобразование будет работать только в том случае, если метод является синхронным (в этом случай не возвращает обещание), или он возвращает обещание, которое уже разрешит (что означает, что вам вообще не требуется преобразование — просто return .

Ответ 2

Сегодня я также столкнулся с этой проблемой и нашел решение.

fetch('http://localhost:3000/hello') .then(dataWrappedByPromise => dataWrappedByPromise.json()) .then(data => < // you can access your data here console.log(data) >) 

Здесь dataWrappedByPromise является экземпляром Promise . Чтобы получить доступ к данным в экземпляре Promise , я обнаружил, что мне просто нужно развернуть этот экземпляр с помощью .json() .

Ответ 3

Этот пример относится к реакции, но по большей части он должен быть таким же.

Замените this.props.url своим URL-адресом, чтобы он работал для большинства других фреймворков.

Разбор res.json() возвращает [[promValue]], однако, если вы затем вернете его другому методу .then() ниже, вы можете вернуть его как полный массив.

let results = fetch(this.props.url) .then((res) => < return res.json(); >) .then((data) => < return data; >) 

Ответ 4

Чтение manpage, мы можем видеть, что:

По дизайну мгновенное состояние и ценность обещания не могут быть проверяется синхронно от кода, не вызывая метод then() .

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

Акцент мой. Поэтому то, что вы хотите сделать, не может быть сделано. Лучший вопрос, почему вам нужно получить доступ к этому обещанию?

Ответ 5

Вот способ получить доступ к PromiseValue ( promise ):

 let promises = definitions; Promise.all(promises).then((promise) => < console.log('promises = ', promises); console.log('promise = ', promise); >); 

Ответ 6

Я думаю, что с этим все будет хорошо.

Ответ 7

Небольшое изменение/расширение предоставленных решений

Для случая, когда ответом является HTML, а не JSON

fetch('http://localhost:3000/hello') .then(response => response.text()) .then(data => < // you can see your PromiseValue data here console.log(data) >) 

Ответ 8

Попробуйте использовать await.

var value = definitions.PromiseValue 
var value = await definiton; 

Это может решить вашу цель путем получения значения обещания.

Обратите внимание, что await можно использовать только внутри асинхронных функций, и это функция ES2016.

Источник

Оцените статью