Ответ 1
Я думаю, что основное преимущество заключается в том, чтобы иметь возможность контролировать, что отображается при перечислении свойств объекта, таких как for in
или Object.keys()
.
MDN хорошо объясняет это с помощью Object.defineProperty
: https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Object/defineProperty
Так обычно, когда люди хотят добавить метод к Object
, например, polyfill для некоторого метода, который не поддерживается в старых браузерах, они изменяют .prototype
. Но это делает свойство перечислимым и запутывает то, что возвращается в коллекции циклов/ключей (без использования .hasOwnProperty
), который не каждый использует).
Итак, вместо чего-то вроде:
Object.prototype.myMethod = function () {
alert("Ahh");
};
вы можете использовать Object.defineProperty
, чтобы явно сказать, что он не может быть перечислим:
Object.defineProperty(Object.prototype, 'myMethod', {
value: function () {
alert("Ahh");
},
enumerable: false
});
Таким образом, например, когда вы используете for (var key in obj)
, "myMethod" не будет перечисляемым элементом, и вам не придется беспокоиться об использовании .hasOwnProperty
. Основная проблема заключается в том, что некоторые браузеры, конечно, не поддерживают его: http://kangax.github.com/es5-compat-table/ и что не все библиотеки/код используют его, поэтому вы не всегда можете полагаться на внешние библиотеки/код для правильного использования и все время.
Вы можете получить доступ к неперечислимому свойству в любое время, оно просто не появится при перечислении свойств объекта - это основная точка.
И я верю, что все "предопределенные" свойства объектов неперечислимы. Тем самым я действительно имею в виду только собственные свойства, не обязательно унаследованные или созданные. Итак, в вашем примере pop
и push
будут перечислены не, но Array.prototype.indexOf
будет, если он создан как polyfill в старом браузере, который не поддерживает этот метод... который, конечно, можно избежать, используя Object.defineProperty
, как мой пример выше. Другим примером является свойство length
, которое не перечислимо.
Вот пример в целом: http://jsfiddle.net/aHJ3g/
Использование и определение Object.keys
имеет важное значение: "Возвращает массив заданных объектов собственных перечислимых свойств в том же порядке, что и в цикле for-in
(разница состоит в том, что цикл цикла for-in
перечисляется свойства в прототипной цепочке). - от MDN - https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Object/keys