2012-11-05 8 views
7

Pracuję nad projektem JavaScript i zastanawiałem się, dlaczego instancja obiektu nie dziedziczy defineProperty() i innych metod, zamiast wywoływać metodę superklasy (superobiektu?) Object.Dlaczego to obiekt Object.defineProperty() zamiast this.defineProperty() (dla obiektów)?

Spojrzałem na MDN docs i istnieją w rzeczywistości "niestandardowe" metody właściwości.

Ale są one przestarzałe. Dlaczego ruch miałby polegać na metodach Object?

Wydaje mi się, że coś takiego jak instance.defineProperty(...) jest lepsze niż Object.defineProperty(instance, ...). Powiedziałbym to samo o niektórych innych metodach Object.

+0

ściśle związane: [Dlaczego nie metody obiektu ES5 dodany do Object.prototype?] (Http: // stackoverflow. com/q/9735026/1048572) – Bergi

Odpowiedz

7

Pozwala uniknąć kolizji - ogólnie rzecz biorąc, problemy z obiektami, które nie mają właściwości o oczekiwanej wartości.
Obiekty w JS są często używane jako mapy klucz-wartość, a klucze mogą być arbitralnymi ciągami znaków - na przykład __defineGetter__, hasOwnProperty lub czymś mniej specjalnym. Teraz, gdy chcesz wywołać taką funkcję na nieznanym obiekcie - np. hasOwnProperty jest często używana w ogólnych funkcjach wyliczeniowych, gdzie można przekazać dowolny JSON - nigdy nie możesz być pewien, czy masz nadpisaną właściwość (która może nawet nie być funkcja) lub oryginalny, który chcesz, lub czy obiekt w ogóle dziedziczy własność. Aby uniknąć tego problemu (lub też this IE bug), musisz użyć Object.prototype.hasOwnProperty.call - to jest brzydkie.

Przypisywanie nazw wszystkich funkcji na Object jest użyteczne, jest to czystszy interfejs API, który oddziela metody analizy od interfejsu aplikacji obiektu. Pomaga to również w optymalizacji (upraszczając analizę statyczną) i ułatwia ograniczenie dostępu do interfejsu API do analizy w piaskownicach - przynajmniej taki był design idea.

Możesz być szczęśliwy mając w prototypie defineProperty, ale możesz go bezpiecznie używać tylko podczas pracy ze znanymi obiektami. Jeśli nadal chcesz go (jak wiesz, kiedy należy używać, a kiedy nie), można użyć

Object.defineProperty(Object.prototype, "defineProperty", { 
    writable: true, 
    enumberable: false, 
    value: function(prop, descr) { 
     return Object.defineProperty(this, prop, descr); 
    } 
}); 
+7

Warto również zauważyć, że obiekty nie muszą dziedziczyć z 'Object.prototype' w ES5. Mogą dziedziczyć z niczego poprzez 'Object.create (null)' lub mogą dziedziczyć po obiekcie, który dziedziczy po 'null'. Jest to bardzo użyteczne zachowanie, ale jeśli obiekt nie dziedziczy po 'Object.prototype', nie będzie miał metod zdefiniowanych w' Object.prototype'.Wszelkie biblioteka chcąc użyć 'defineProperty' rodzajowo musiałby zrobić' var defineProperty = Function.prototype.call.bind (Object.prototype.defineProperty); ', więc to ma sens tylko do określenia go jako funkcji użyteczności i tak zamiast metoda. –

+1

@Nathan: Bardzo dobre punkty, dziękuję. – Bergi

+0

Faktycznie, prawdziwym powodem jest dla piaskownice i lepszego API - mogę to udowodnić, ale „rationale_for_es3_1_static_object_methodsaug26.pdf” jest martwy. –

2

Interesujące. Jedynym powodem, dla którego do tej pory doszedłem, jest to, że ludzie lubią przepisywać prototypy i mieć tę metodę "ukrytą" w ten sposób, aby pomóc ci uniknąć błędów. Zwłaszcza ze względu na dobrą nazwę metody, ponieważ jest bardziej prawdopodobne, że zostanie przepisana niż na przykład __defineGetter__.

Wygląda na to, że wiele funkcji zależy od tej funkcjonalności (link), więc ma sens uczynienie go bardziej globalnym i bezpiecznym w tym kontekście.

2

Jest to zrobione w ten sposób, aby uniknąć kolizji - pamiętaj, że każda metoda na Object.prototype jest metodą w każdym pojedynczym obiekcie zdefiniowanym przez użytkownika.

Wyobraź sobie obiekt, w którym chcesz niestandardowej metody defineProperty - który całkowicie zepsuje rzeczy, gdy Object.defineProperty był na swoim prototypem.

Powiązane problemy