Довжина об’єкта в JavaScript
9 Липня 2019
наступна стаття
Можливо дехто і буде здивований, але визначити довжину Object
простим викликом length
на об’єкті — неможливо! Переконайтеся самі:
var object = { first: 1, second: 2 }; object.length // undefined
Як би ми не старалися нічого не вийде, оскільки в Object
немає параметру length
. Він присутній лише у таких типів даних як array
та string
:
var object = { first: 1, second: 2 }; var string = 'string'; var array = [1,2,3]; object.hasOwnProperty('length'); // false string.hasOwnProperty('length'); // true array.hasOwnProperty('length'); // true
Шлях до визначення довжини
На відміну від масивів, отримати довжину об'єкта завжди було складно. Object.keys()
повертає enumerated
-масив всіх ключів властивостей об'єкта, а після цього можна просто використати length
та отримати його довжину.
var object = { first: 1, second: 2 }; Object.keys(object).length; // 2
Але на практиці не все так просто, як із першого погляду. Тому для більш детального пояснення було б добре розібратись в походженні цього enumerated
масиву.
Як правило, коли ми хочемо додати властивість до об'єкта, ми можемо це зробити за допомогою крапки:
var object = { first: 1}; object.second = 2; console.log(object); // { first: 1, second: 2 }
Альтернативним шляхом може бути використати Object.defineProperty() який приймає три параметри: obj, prop, descriptor. Enumerated
-атрибут можна вказати якраз у descriptor:
const object = {}; Object.defineProperty( object, 'first', { value: '1', enumerable: true } ); console.log(object); // { first: '1' }
Автоматичне визначення
Давайте повернемося до нашого прикладу властивостей об'єкта, що ми встановили за допомогою крапки. Чому він відображався автоматично? Це відбувається тому, що коли ми вказуємо властивість, атрибут enumerable
автоматично встановлюється як значення true.
var object = {}; object.first = 1; object.propertyIsEnumerable(first); // true
У більшості випадків ми б не використовували enumerable
-атрибут для визначення length
. Це просто надійний спосіб контролювати, чи буде створена властивість видимою, чи прихованою, коли ми перебираємо об'єкт за допомогою Object.keys
.
Таким чином, атрибут enumerable
використовується для приховування властивостей, що не слід повторювати. Це стало причиною введення перелічуваності в ECMAScript 1.
const object = {first: '1'}; Object.defineProperty( object, 'second', { value: '2', enumerable: false } ); Object.keys(object); // [ 'first' ] Object.getOwnPropertyNames(object); // [ 'first', 'second' ]
Як можна зрозуміти з прикладу вище, Object.getOwnPropertyNames
поверне масив з іменами усіх ключів, в той час як Object.keys
поверне масив імен тільки enumerable
-ключів. Здавалося б, що краще використовувати метод Object.getOwnPropertyNames
для знаходження length
. Але швидше всього, ці параметри об’єкту не є enumerable
та мають бути приховані. Тому використовувати в даному контексті Object.getOwnPropertyNames
— не найкраща ідея.
Додаткові можливості
Перед початком використання Object.keys
за замовчуванням для знаходження length
об’єкта, необхідно зробити невелику ремарку. В стандарті ECMAScript 6, ES6, представлений новий тип даних — symbol
. Його використання можливе у якості імені ключа властивості об’єкта.
const obj = { [Symbol('first')]: 1, second: 2 };
Але за таких умов як Object.keys
так і Object.getOwnPropertyNames
не будуть працювати так, як від них вимагається.
Object.keys(obj) // ["second"] Object.getOwnPropertyNames(obj) // ["second"]
Як бачимо, символьний ключ відсутній в обох масивах. Рішеням цієї проблеми буде використання Object.getOwnPropertySymbols
:
Object.getOwnPropertySymbols(obj) // [Symbol(first)]
Таким чином ми отримали масив тільки з імен ключів властивостей типу symbol.
І тепер для отримання length нам необхідно просто скомбінувати обидва методи:
const symbolsLength = Object.getOwnPropertySymbols(obj); const withoutSymbolLength = Object.keys(obj); const length = symbolsLength + withoutSymbolLength;
Ми зв'яжемось з Вами протягом 10 хвилин