2013-02-20 2 views
39

Перечислимость является одним из трех атрибутов свойства: возможность записи, перечислимость и конфигурируемость. Мои вопросы:Каковы преимущества внесения свойств, не подлежащих перечислению?

  • В чем преимущество создания свойств, не подлежащих перечислению на JavaScript? Я знаю, что мы скрываем собственность, делая их неперечислимыми, но в чем преимущество скрытия собственности?
  • Можем ли мы получить доступ к неперечислимым свойствам? Если да, то в чем преимущество сделать их неперечислимыми?
  • Все предопределенные свойства объектов, заданных как неперечислимые? Например, если объекты Array's pop и push не перечислимы?
+1

Я думаю, что главное преимущество заключается сделать 'для в' петли сейф - свойство не будет отображаться при переборе над объектом. Может быть, я забываю, что такое перечислимость ... – Ian

+2

Связанные: [Что такое преимущества и опасности добавления методов Object.prototype в Javascript?] (Http://stackoverflow.com/questions/3832617/what-are-the -Преимущества-и-опасности-о-добавляющих-методов-объект-прототип-в-Javas? RQ = 1). –

ответ

35

Я думаю, что главное преимущество должно быть в состоянии для контроля того, что отображается при перечислении свойств объекта, например 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 будет, если он создан как полиполк в старом браузере, который не поддерживает этот метод ...чего, конечно, можно избежать, используя 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

2
  • Делая свойство несчетным вы можете получить доступ к нему. Но когда вы применяете цикл for for для объекта, свойство non-enumerable не будет итерировано.
  • См первая точка
  • наследуемых свойств встроенных объектов (например, толчок, поп, ToString ...) не перечислимы

    var o = {a:1, b:2, c:3} // a,b,c are enumerable properties 
    o.propertyIsEnumerable("toString") // returns false, because it is a inherited property 
    for(p in o) console.log(p); // this loop will print a,b and c but not toString or other inherited properies 
    
+2

Я считаю, что третий пункт неверен. Унаследованные свойства, безусловно, такие же перечислимые, как и любые другие ... 'var x = {a: 1}; var y = Object.create (x); y.b = 2; for (name in y) {console.log (имя, y [имя]);} 'дает' b 2' и 'a 1'. –

+0

Вы правы! Унаследованные свойства также перечислены. Если вы просто хотите, чтобы собственные и перечислимые свойства использовали Object.keys(). – daniatic

11

Другим важным преимуществом, которое я вижу, является то, что он не позволяет частным свойствам объекта загрязнять общедоступное пространство имен.

Скажите, что вы создали и опубликовали мощную библиотеку под названием Cosmos. Пользователь запускает интерпретатор узла и создает новый экземпляр, вызвав конструктор:

var Cosmos = require('Cosmos'); 
var cosmos = new Cosmos('my empire'); 

Теперь пользователь просто типы cosmos и прессы ввести, чтобы увидеть, что публичный API поддерживает. Какой из них вы хотите видеть?

{ name: 'my empire', 
    grow: [Function: grow], 
    addStar: [Function: addStar], 
    beautify: [Function: beautify], 
    implode: [Function: implode], 
    destroy: [Function: destroy] } 

ИЛИ

{ _age: 25000, 
    _size: 35000, 
    _destroyed: false, 
    name: 'my empire', 
    _numStars: 200, 
    _init: [Function: _init], 
    grow: [Function: grow], 
    _grow: [Function: _grow], 
    addStar: [Function: addStar], 
    _checkStatus: [Function: _checkStatus], 
    beautify: [Function: beautify], 
    implode: [Function: implode], 
    destroy: [Function: destroy] } 
+3

Неперечислимые свойства остаются общедоступными и все еще загрязняют пространство имен. Если вам нужны частные объекты, вам необходимо закрыть. – Matthew

+4

Я поддержал как ответ, так и критический комментарий. Критика комментария кажется мне действительной, поэтому, возможно, использование ответчиком «публичных» и «частных» может оказаться не оптимальным. Тем не менее, я думаю, что точка ответа по-прежнему полезна (по крайней мере, для меня), потому что она показывает, как перечислимость может помочь пользователю библиотеки более легко увидеть, что автор библиотеки предназначил для пользователя библиотеки, чтобы его легко использовать (например, расти, а не '_grow', даже если оба они по-прежнему технически общедоступны). –

 Смежные вопросы

  • Нет связанных вопросов^_^