Object.keys, values, entries
Давайте отойдём от отдельных структур данных и поговорим об их переборе вообще.
В предыдущей главе мы видели методы map.keys() , map.values() , map.entries() .
Это универсальные методы, и существует общее соглашение использовать их для структур данных. Если бы мы делали собственную структуру данных, нам также следовало бы их реализовать.
Методы поддерживаются для структур:
Простые объекты также можно перебирать похожими методами, но синтаксис немного отличается.
Object.keys, values, entries
Для простых объектов доступны следующие методы:
- Object.keys(obj) – возвращает массив ключей.
- Object.values(obj) – возвращает массив значений.
- Object.entries(obj) – возвращает массив пар [ключ, значение] .
Обратите внимание на различия (по сравнению с map , например):
Map | Object | |
---|---|---|
Синтаксис вызова | map.keys() | Object.keys(obj) , не obj.keys() |
Возвращает | перебираемый объект | «реальный» массив |
Первое отличие в том, что мы должны вызвать Object.keys(obj) , а не obj.keys() .
Почему так? Основная причина – гибкость. Помните, что объекты являются основой всех сложных структур в JavaScript. У нас может быть объект data , который реализует свой собственный метод data.values() . И мы всё ещё можем применять к нему стандартный метод Object.values(data) .
Второе отличие в том, что методы вида Object.* возвращают «реальные» массивы, а не просто итерируемые объекты. Это в основном по историческим причинам.
let user = < name: "John", age: 30 >;
- Object.keys(user) = [«name», «age»]
- Object.values(user) = [«John», 30]
- Object.entries(user) = [ [«name»,»John»], [«age»,30] ]
Вот пример использования Object.values для перебора значений свойств в цикле:
let user = < name: "John", age: 30 >; // перебор значений for (let value of Object.values(user)) < alert(value); // John, затем 30 >
Object.keys/values/entries игнорируют символьные свойства
Так же, как и цикл for..in , эти методы игнорируют свойства, использующие Symbol(. ) в качестве ключей.
Обычно это удобно. Но если требуется учитывать и символьные ключи, то для этого существует отдельный метод Object.getOwnPropertySymbols, возвращающий массив только символьных ключей. Также, существует метод Reflect.ownKeys(obj), который возвращает все ключи.
Трансформации объекта
У объектов нет множества методов, которые есть в массивах, например map , filter и других.
Если мы хотели бы их применить, то можно использовать Object.entries с последующим вызовом Object.fromEntries :
- Вызов Object.entries(obj) возвращает массив пар ключ/значение для obj .
- На нём вызываем методы массива, например, map .
- Используем Object.fromEntries(array) на результате, чтобы преобразовать его обратно в объект.
Например, у нас есть объект с ценами, и мы хотели бы их удвоить:
let prices = < banana: 1, orange: 2, meat: 4, >; let doublePrices = Object.fromEntries( // преобразовать в массив, затем map, затем fromEntries обратно объект Object.entries(prices).map(([key, value]) => [key, value * 2]) ); alert(doublePrices.meat); // 8
Это может выглядеть сложным на первый взгляд, но становится лёгким для понимания после нескольких раз использования.
Можно делать и более сложные «однострочные» преобразования таким путём. Важно только сохранять баланс, чтобы код при этом был достаточно простым для понимания.
Задачи
Сумма свойств объекта
важность: 5
Есть объект salaries с произвольным количеством свойств, содержащих заработные платы.
Напишите функцию sumSalaries(salaries) , которая возвращает сумму всех зарплат с помощью метода Object.values и цикла for..of .
Если объект salaries пуст, то результат должен быть 0 .
let salaries = < "John": 100, "Pete": 300, "Mary": 250 >; alert( sumSalaries(salaries) ); // 650
function sumSalaries(salaries) < let sum = 0; for (let salary of Object.values(salaries)) < sum += salary; >return sum; // 650 > let salaries = < "John": 100, "Pete": 300, "Mary": 250 >; alert( sumSalaries(salaries) ); // 650
Или, как вариант, мы можем получить сумму, используя методы Object.values и reduce :
// reduce перебирает массив значений salaries, // складывает их // и возвращает результат function sumSalaries(salaries) < return Object.values(salaries).reduce((a, b) =>a + b, 0) // 650 >
JS hasOwnProperty() — поиск ключа в объекте
Данный метод мы можем использовать для поиска ключа в объекте.
Допустим у нас есть объект и мы хотим проверить есть ли в нем заданный ключ. Мы могли бы воспользоваться перебором объекта в цикле, но если нам нужно просто получить true или false , то гораздо проще будет использовать метод hasOwnProperty()
const someObj = < 'key1': 'value 1', 'key2': 'value 2', 'key3': 'value 3', 'key4': 'value 4', >console.log(someObj.hasOwnProperty('key1')); // true console.log(someObj.hasOwnProperty('key11')); // false
Кроме того, данный метод будет необходим, если вы проходитесь по объекту в цикле for . in , так как данный цикл проходит и по прототипу объекта.
Давайте рассмотрим такой пример. У нас есть объект product , у него есть 3 свойства. Далее есть объект anotherProduct , у него есть свои 3 свойства, а также он наследует свойства из объекта product :
const product = < size: 'M', width: 100, height: 150 >for (let key in product) < console.log(`$- $`); > // Выведет: // size - M // width - 100 // height - 150 const anotherProduct = < sleeve: true, color: 'red', weight: 100, __proto__: product >for (let key in anotherProduct) < console.log(`$- $`); > // Выведет все свойства, включая прототип: // sleeve: true // color: red // weight: 100 // size - M // width - 100 // height - 150
Проходя циклом по данным объектам выведем их в консоль. Так вот в первом случае мы в консоли увидим 3 свойства, а во втором 6.
В случае, если вам не нужны свойства прототипа, вы можете использовать метод hasOwnProperty , который проверит принадлежит ли данной свойство итерируемому объекту или его прототипу:
for (let key in anotherProduct) < if (anotherProduct.hasOwnProperty(key)) console.log(`$- $`); > // Выведет только: // sleeve: true // color: red // weight: 100
Как проверять наличие ключа в объекте?
От сервера приходит ответ в формате json: response.data при успехе, response.error при ошибке. Как проверять, существует ли в ответе data или error? В php например есть функция isset, а что у js?
Есть вариант использовать это:
if (typeof obj.foo !== 'undefined') < // your code here >
но не костыльный ли это вариант?
- Вопрос задан более трёх лет назад
- 1902 просмотра
1 комментарий
Простой 1 комментарий
foo in obj
Решения вопроса 1
Гугли и ты откроешь врата знаний!
const object = < prop1: 'value1' >; // https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Global_Objects/Object/hasOwnProperty if (object.hasOwnProperty('prop1')) < // your code here >// Тоже самое, что и 1й, но немного отличается своей работой // https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Global_Objects/Object/hasOwnProperty#Example_hasOwnProperty_as_a_property if (Object.prototype.hasOwnProperty.call(object, 'prop1')) < // your code here >if (object.prop1) < // your code here >if (typeof object.prop1 !== 'undefined') < // your code here >if ('prop1' in object) < // your code here >
Ответ написан более трёх лет назад
Нравится 4 2 комментария
hasOwnProperty хоть и самый нормальный, но он в 10 раз медленнее typeof
const object = < prop1: 'value1' >; let i = null; console.time('typeof'); i = 0; do < i++; if (typeof object.prop1 !== "undefined") < // your code here >> while (i < 10e6); console.timeEnd('typeof'); console.time('hasOwnProperty'); i = 0; do < i++; if (object.hasOwnProperty('prop1')) < // your code here >> while (i < 10e6); console.timeEnd('hasOwnProperty');
typeof: 11.98ms
hasOwnProperty: 106.832ms
Евгений, потому что они призваны делать разные вещи. Получение типа и существование свойства разные задачи. Я высказал своё мнение и при нём и останусь, и продолжу использовать для проверки существования свойства именно этот метод. Вы можете делать так, как вы считаете нужным, я не против. В любом случае, я привел достаточно вариантов проверки. Чаще всего достаточно просто
if (object.prop1) <>
Object.prototype.hasOwnProperty()
Метод hasOwnProperty() возвращает логическое значение, указывающее, содержит ли объект указанное свойство.
Синтаксис
obj.hasOwnProperty(prop)
Параметры
Имя проверяемого свойства.
Описание
Каждый объект, произошедший от Object , наследует метод hasOwnProperty . Этот метод может использоваться для определения того, содержит ли объект указанное свойство в качестве собственного свойства объекта; в отличие от оператора in , этот метод не проверяет существование свойств в цепочке прототипов объекта.
Примеры
Пример: использование hasOwnProperty для проверки существования свойства
В следующем примере определяется, содержит ли объект o свойство с именем prop :
= new Object(); o.prop = "существует"; function changeO() o.newprop = o.prop; delete o.prop; > o.hasOwnProperty("prop"); // вернёт true changeO(); o.hasOwnProperty("prop"); // вернёт false
Пример: собственные и унаследованные свойства
Следующий пример показывает разницу между собственными свойствами и свойствами, унаследованными через цепочку прототипов:
= new Object(); o.prop = "существует"; o.hasOwnProperty("prop"); // вернёт true o.hasOwnProperty("toString"); // вернёт false o.hasOwnProperty("hasOwnProperty"); // вернёт false
Пример: обход свойств объекта
Следующий пример показывает, как итерироваться по свойствам объекта с пропуском унаследованных свойств. Обратите внимание, что цикл for. in уже проходит только по перечисляемым элементам, так что не надо на основании отсутствия не перечисляемых свойств, показываемых в цикле, считать, что метод hasOwnProperty сам ограничивает свойства только перечисляемыми элементами (как это делает метод Object.getOwnPropertyNames() ).
var buz = fog: "stack", >; for (var name in buz) if (buz.hasOwnProperty(name)) alert("это точно туман (" + name + "). Значение: " + buz[name]); > else alert(name); // toString или что-то ещё > >
Пример: hasOwnProperty как свойство
JavaScript не защищает имя свойства hasOwnProperty ; таким образом, вполне может существовать объект с таким свойством, поэтому для получения правильного результата нужно использовать внешний метод hasOwnProperty :
var foo = hasOwnProperty: function () return false; >, bar: "Тут драконы", >; foo.hasOwnProperty("bar"); // всегда возвращает false // Используем метод hasOwnProperty другого объекта и вызываем его с передачей foo в качестве this (>).hasOwnProperty.call(foo, "bar"); // true // Также для этих целей можно использовать свойство hasOwnProperty из прототипа Object Object.prototype.hasOwnProperty.call(foo, "bar"); // true
Обратите внимание, что в последнем случае новые объекты не создаются.
Спецификации
Specification |
---|
ECMAScript Language Specification # sec-object.prototype.hasownproperty |
Совместимость с браузерами
BCD tables only load in the browser
Смотрите также
- Перечисляемость и собственность свойств (en-US)
- Object.getOwnPropertyNames()
- for. in
- in
- Руководство по JavaScript: повторное наследование (en-US)
Found a content problem with this page?
- Edit the page on GitHub.
- Report the content issue.
- View the source on GitHub.
This page was last modified on 7 авг. 2023 г. by MDN contributors.
Your blueprint for a better internet.