
В отличие от массивов, всегда было сложно определить длину объекта. Ну не более!
Object.keys возвращает массив всех перечислимых ключей свойств объекта. А после этого вы можете просто позвонить length и вуаля! У вас есть длина объекта 🎉
const object = {one: '1️⃣', two: '2️⃣'};
// Using Lodash
_.size(object); // 2
// Using JavaScript
Object.keys(object).length; // 2
Почему мы не можем вызвать length для объекта
Вам может быть интересно, почему мы не можем просто вызвать length прямо на нашем объекте. Посмотрим, что произойдет, когда мы это сделаем:
const object = {one: '1️⃣', two: '2️⃣'};
object.length; // undefined
object.hasOwnProperty('length'); // false
Вы не можете этого сделать, потому что object не имеет свойства length. Только string и arrays имеют свойство length.
const string = 'hello';
const array = [1,2,3];
string.hasOwnProperty('length'); // true
array.hasOwnProperty('length'); // true
Что такое перечисления
Хорошо, давайте перейдем к другой теме. В начале я упоминал, что Object.keys возвращает массив ключей свойств перечислимого. Итак, давайте выясним, откуда взялся этот атрибут enumerable.
Назначение собственности
Обычно, когда мы хотим добавить свойство к объекту, мы можем просто использовать точечную нотацию:
const object = {};
object.one = '1️⃣';
console.log(object); // { one: '1️⃣' }
Определение свойства
В качестве альтернативы мы также можем использовать Object.defineProperty. Он принимает 3 параметра. И это в дескрипторе свойства, где мы можем установить наш перечисляемый атрибут.
Object.defineProperty(object name, property name, property descriptor)
Хорошо, давайте определим свойство с помощью этого метода:
const object = {};
Object.defineProperty(
object,
'one', {
value: '1️⃣'
}
);
console.log(object); // {}
// 👆Why is it empty? 🤔
Хммм ... это странно. Почему не отображалось наше свойство 🤔 Это потому, что, когда мы определяем свойство таким образом, атрибут enumerable по умолчанию равен false. Поэтому, если мы хотим, чтобы он отображался, нам нужно установить для него true.
const object = {};
Object.defineProperty(
object,
'one', {
value: '1️⃣',
enumerable: true // 👈
}
);
console.log(object); // { one: '1️⃣' }
// 👆 Great, it shows up now!
Enumerable по умолчанию - true
Вернемся к нашему примеру свойства объекта, которое мы установили с помощью точечной записи. Почему это появилось автоматически? Это потому, что, когда мы назначаем свойство таким образом, атрибут enumerable автоматически устанавливается на true.
const object = {};
object.one = '1️⃣';
object.propertyIsEnumerable('one'); // true
Перечислимое резюме
Для большинства из нас мы редко касаемся атрибута enumerable при определении нашего свойства. Это просто способ контролировать, будет ли определенное свойство, которое мы создали, отображаться или оставаться скрытым, когда мы перебираем объект с помощью Object.keys.
Если вы хотите узнать больше о перечислимости, я рекомендую прочитать эту статью Перечислимость в ECMAScript 6.
Следовательно, перечисляемый атрибут используется для скрытия свойств, которые не следует повторять. Это было причиной введения перечислимости в ECMAScript 1.
Доктор Аксель Раушмайер, 2Ality
Object.keys против Object.getOwnPropertyNames
Теперь, когда вы понимаете enumerable, давайте рассмотрим другой метод, который вы можете увидеть как вариант для получения длины, Object.getOwnPropertyNames.
const object = {one: '1️⃣'};
Object.defineProperty(
object,
'two', {
value: '2️⃣',
enumerable: false
}
);
Object.keys(object); // [ 'one' ]
Object.getOwnPropertyNames(object); // [ 'one', 'two' ]
Как видите, Object.getOwnPropertyNames вернет ВСЕ ключи свойств, тогда как Object.keys вернет только перечислимые ключи свойств. Как я уже упоминал ранее, перечислимые атрибуты могут быть скрыты по какой-то причине, поэтому вы можете не захотеть получить к ним доступ. Следовательно, Object.getOwnPropertyName может быть не тем методом, который вы хотите использовать для получения длины объекта.
Длина объекта с символами
Перед тем, как вы по умолчанию используете Object.keys, чтобы получить длину объекта. Хочу отметить еще одно соображение. В ECMAScript 6, ES6, был представлен новый примитивный тип данных под названием symbol. И вы можете использовать symbol как имя свойства объекта.
const animal = {
[Symbol('ghost')]: '👻',
turtle: '🐢'
};
Но проблема в том, что в качестве имени свойства используется symbol. Object.keys и Object.getOwnPropertyNames работать не будут.
Object.keys(animal); // [ 'turtle' ] <-- no symbol Object.getOwnPropertyNames(animal); // [ 'turtle' ] <-- no symbol
Итак, решение - использовать Object.getOwnPropertySymbols
Object.getOwnPropertySymbols(animal); // [ Symbol(ghost) ]
Теперь, объединив два метода, вы получите нужную длину.
const enumerableLength = Object.keys(animal).length; const symbolLength = Object.getOwnPropertySymbols(animal).length; const totalObjectLength = enumerableLength + symbolLength; // 2 <-- 👍
Ресурсы
- Веб-документы MDN: Object.keys
- Веб-документы MDN: Object.getOwnPropertyNames
- Веб-документы MDN: Object.getOwnPropertySymbols
- Веб-документы MDN: Объект
- 2ality: перечислимость в ES6
- 2ality: определение свойства против присвоения
- Переполнение стека: когда использовать Object.defineProperty
- Переполнение стека: как использовать javascript Object.defineProperty
- Переполнение стека: Object.getOwnPropertyNames vs Object.keys
- Переполнение стека: длина объекта JavaScript
Делиться
- Нравится в Твиттере
- Нравится в Instagram
- Первоначально опубликовано на www.samanthaming.com.
Спасибо за чтение ❤
Сказать привет! Instagram | Facebook | Твиттер | SamanthaMing.com | Блог