Чи дають наступні два твердження однаковий результат? Чи є якась причина віддавати перевагу одному способу іншому?
if (key in object)
if (object.hasOwnProperty(key))
Чи дають наступні два твердження однаковий результат? Чи є якась причина віддавати перевагу одному способу іншому?
if (key in object)
if (object.hasOwnProperty(key))
Відповіді:
Будьте уважні - вони не дадуть однакового результату.
inтакож повернеться, trueякщо keyйого знайдуть десь у ланцюзі прототипу , тоді як Object.hasOwnProperty(як і назва вже нам розповідає), він повернеться лише в тому trueвипадку, якщо він keyбуде доступний безпосередньо для цього об'єкта (його "володіє" властивістю).
({foo:"bar"}).hasOwnProperty("toString")vs"toString" in ({foo:"bar"})
Спробую пояснити іншим прикладом. Скажімо, у нас є наступний об'єкт з двома властивостями:
function TestObj(){
this.name = 'Dragon';
}
TestObj.prototype.gender = 'male';
Створимо примірник TestObj:
var o = new TestObj();
Розглянемо примірник об'єкта:
console.log(o.hasOwnProperty('name')); // true
console.log('name' in o); // true
console.log(o.hasOwnProperty('gender')); // false
console.log('gender' in o); // true
Висновок:
в операторі повертає істину завжди, якщо властивість доступна об'єктом, безпосередньо або з прототипу
hasOwnProperty () повертає true лише в тому випадку, якщо властивість існує в екземплярі, але не в його прототипі
Якщо ми хочемо перевірити, чи існує якась властивість у прототипі, ми би сказали:
console.log(('name' in o) && !o.hasOwnProperty('name')); //false
console.log(('gender' in o) && !o.hasOwnProperty('gender')); //true - it's in prototype
Нарешті:
Отже, щодо твердження, що ці дві умови ...
if (key in object)
if (object.hasOwnProperty(key))
... дають той же результат, відповідь очевидна, це залежить.
inтакож перевірить наявність успадкованих властивостей, що не стосується hasOwnProperty.
Підсумовуючи це, hasOwnProperty()він не виглядає в прототипі, а inне в прототипі.
Взято з високоефективного Javascript від O'Reilly :
Ви можете визначити, чи є в об'єкта член екземпляра із заданим іменем, скориставшись методом hasOwnProperty () та передавши ім’я члена. Щоб визначити, чи має об’єкт доступ до властивості з певним іменем, можна скористатися оператором in. Наприклад:
var book = {
title: "High Performance JavaScript",
publisher: "Yahoo! Press"
};
alert(book.hasOwnProperty("title")); //true
alert(book.hasOwnProperty("toString")); //false
alert("title" in book); //true
alert("toString" in book); //true
У цьому коді hasOwnProperty () повертає значення true, коли передається "title", оскільки title є об'єктом об'єкта; метод повертає false, коли передається "toString", оскільки його немає в екземплярі. Коли кожне ім'я властивості використовується разом з оператором in, результат істинний обох разів, оскільки він шукає екземпляр та прототип.
Ви отримали кілька справді чудових відповідей. Я просто хочу запропонувати щось, що позбавить вас від необхідності перевірити "hasOwnProperty" під час ітерації об'єкта.
Створюючи об'єкт, зазвичай люди створюють його таким чином:
const someMap = {}
// equivalent to: Object.create(Object.prototype)
// someMap.constructor will yield -> function Object() { [native code] }
Тепер, якщо ви хочете повторити через "someMap", вам доведеться зробити це так:
const key
for(key in someMap ){
if (someMap.hasOwnProperty(key)) {
// Do something
}
}
Ми робимо це для того, щоб уникнути повторення над успадкованими властивостями.
Якщо ви маєте намір створити простий об'єкт, який буде використовуватися лише як "карта" (тобто пари ключ - значення), ви можете зробити так:
const newMap = Object.create(null);
// Now, newMap won't have prototype at all.
// newMap.constructor will yield -> undefined
Тож тепер це буде безпечно повторювати так:
for(key in cleanMap){
console.log(key + " -> " + newMap [key]);
// No need to add extra checks, as the object will always be clean
}
Я дізнався цю дивовижну пораду тут
Інша форма (викликається в) перераховує назви властивостей (або ключів) об'єкта. На кожній ітерації змінній присвоюється інший рядок імені властивості від об'єкта. Зазвичай потрібно протестувати object.hasOwnProperty (змінної), щоб визначити, чи справді ім'я властивості є членом об'єкта, або було знайдено замість нього в ланцюзі прототипу.
for (myvar in obj) {
if (obj.hasOwnProperty(myvar)) { ... } }
(з Jackson Crockford : Хороші частини )
inОператор відрізняється від for-inзаяви.
inце ключове слово. Але ОП запитує про конкретне використання inоператора. Ваша відповідь стосується іншого використання як частини for-inзаяви.
Перша версія коротша (особливо в мінімізованому коді, де змінні перейменовані)
a in b
проти
b.hasOwnProperty(a)
У будь-якому випадку, як сказав @AndreMeinhold, вони не завжди дають однаковий результат.
in will also return true if key gets found somewhere in the prototype chain. ви можете написати приклад? Дякую.