2013-02-20 18 views
39

Wyliczalność to jeden z trzech atrybutów właściwości: zdolność do pisania, wymienialność i konfigurowalność. Moje pytania są następujące:Jakie są zalety tworzenia właściwości nieprzeliczalnych?

  • Jakie są zalety tworzenia właściwości nieprzeliczalnych w JavaScript? Wiem, że ukrywamy nieruchomość, czyniąc je nieprzeliczalnymi, ale jakie są korzyści ukrywania własności?
  • Czy możemy uzyskać dostęp do nieruchomości nieprzelotowych? Jeśli tak, to jaka jest korzyść z tego, że są one nieprzeliczalne?
  • Czy wszystkie predefiniowane właściwości obiektów są ustawione jako nieprzeliczalne? Tak jak w przypadku właściwości Array'a: pop i push, które są nieprzeliczalne?
+1

Myślę, że główną korzyścią jest to, aby 'dla in' pętle bezpieczne - własność nie pojawi się podczas iteracji nad obiektem. Być może zapominam o tym, co enumerability ma ... – Ian

+2

Powiązane: [Jakie są korzyści i niebezpieczeństwa związane z dodaniem metod do Object.prototype w JavaScript?] (Http://stackoverflow.com/questions/3832617/what-are-the - korzyści i zagrożenia związane z dodawaniem metod do prototypu w javas? rq = 1). –

Odpowiedz

35

Myślę, że główną korzyścią jest to, aby móc aby kontrolować to, co pojawia się podczas wyliczania właściwości obiektu, takich jak for in lub Object.keys().

MDN wyjaśnia to dobrze Object.defineProperty: https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Object/defineProperty

Więc zwykle, gdy ludzie chcą dodać metodę Object, takich jak PolyFill jakiegoś metody nie obsługiwany w starych przeglądarkach one modyfikować .prototype. Ale to powoduje, że właściwość jest wyliczalna i zawodzi, co jest zwracane w kolekcji pętli/kluczy (bez użycia .hasOwnProperty ... której nie każdy używa).

Zamiast więc coś takiego:

Object.prototype.myMethod = function() { 
    alert("Ahh"); 
}; 

można użyć Object.defineProperty wyraźnie powiedzieć, aby nie być przeliczalny:

Object.defineProperty(Object.prototype, 'myMethod', { 
    value: function() { 
     alert("Ahh"); 
    }, 
    enumerable: false 
}); 

W ten sposób, na przykład podczas korzystania for (var key in obj) „myMethod "nie będzie przedmiotem wyliczonym i nie będziesz musiał się martwić o używanie .hasOwnProperty. Głównym problemem jest to, że niektóre przeglądarki nie obsługują go oczywiście: http://kangax.github.com/es5-compat-table/ i że nie wszystkie biblioteki/kod używają go, więc nie zawsze można polegać na zewnętrznych bibliotekach/kodzie, aby używać go poprawnie i przez cały czas.

Możesz uzyskać dostęp do własności nieprzeliczalnej w dowolnym momencie, po prostu nie pojawi się podczas wyliczania właściwości obiektu - to jest główny punkt.

Sądzę, że wszystkie "predefiniowane" właściwości obiektów są nieprzeliczalne. Rozumiem przez to jedynie własności natywne, niekoniecznie odziedziczone lub stworzone. Tak więc na twoim przykładzie, pop i push będzie wyliczone, ale Array.prototype.indexOf będzie, jeśli zostanie utworzone jako polyfill w starej przeglądarce, która nie obsługuje tej metody ...co oczywiście można uniknąć, używając mojego przykładu powyżej. Innym przykładem jest właściwość length, która nie jest wyliczana.

Oto przykład ogólnie: http://jsfiddle.net/aHJ3g/

Stosowanie i definicja Object.keys ważne „Zwraca tablicę własnych właściwości przeliczalnych danego obiektu, w takiej samej kolejności jak te dostarczane przez for-in pętli (różnica jest to, że pętla for-in wylicza również właściwości w łańcuchu prototypów). " - od MDN - https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Object/keys

2
  • Dzięki temu, że nieruchomość jest nieprzeliczalna, nadal można uzyskać do niej dostęp. Ale gdy zastosujesz pętlę for in w obiekcie, nieprzeliczalna właściwość nie będzie iterowana.
  • Zobacz pierwszy punkt
  • dziedziczone właściwości wbudowanych obiektów (takich jak Push, pop, toString ...) nie są przeliczalne

    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

Wierzę, że trzeci punkt jest błędny. Dziedziczone właściwości są z pewnością tak różne, jak wszystkie inne ... 'var x = {a: 1}; var y = Object.create (x); y.b = 2; for (name in y) {console.log (name, y [name]);} 'daje' b 2' i 'a 1'. –

+0

Masz rację! Dziedziczone właściwości są również przeliczalne. Jeśli chcesz mieć własne i przeliczalne właściwości, użyj Object.keys(). – daniatic

11

Inną ważną korzyścią, jaką widzę, jest to, że zapobiega ona zanieczyszczaniu publicznych przestrzeni nazw przez prywatne właściwości obiektu.

Załóżmy, że utworzyłeś i opublikowałeś potężną bibliotekę o nazwie Cosmos. Użytkownik odpala interpreter węzeł i tworzy nową instancję niej przez wywołanie konstruktora:

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

Teraz użytkownik po prostu typy cosmos i prasy wprowadź zobaczyć, co publiczne API obsługuje. Którego z tych dwóch chcesz zobaczyć?

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

LUB

{ _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

właściwości nieprzeliczalne są nadal publiczne i nadal zanieczyszczają przestrzeń nazw. Jeśli chcesz prywatnych nieruchomości, potrzebujesz zamknięcia. – Matthew

+4

Przegłosowałem zarówno odpowiedź, jak i krytyczny komentarz. Krytyka komentarza wydaje mi się słuszna, więc być może użycie "publicznego" i "prywatnego" przez respondenta może nie być optymalne. Jednak myślę, że punkt odpowiedzi jest nadal pomocny (przynajmniej dla mnie), ponieważ pokazuje, w jaki sposób przeliczalność może pomóc użytkownikowi biblioteki w łatwiejszym zobaczeniu, co autor biblioteki zamierzał dla użytkownika biblioteki łatwo użyć (np. rosną, a nie '_grow', nawet jeśli oba są technicznie nadal publiczne). –

Powiązane problemy