2011-05-23 17 views
5

Próbuję zdefiniować niestandardowego ustawiacza dla właściwości innerHTML. Niestety, nie jestem w stanie uzyskać dostępu do właściwości bazowego po tym, jak zdefiniować funkcję seter:Uzyskiwanie dostępu do właściwości ukrytych przez __defineGetter __/__ defineSetter__ w JavaScript

$('body')[0].__defineSetter__("innerHTML", 
    function (val) { 
    alert("Setting to: " + val); 
    this.innerHTML = val; 
}); 

Ten fragment wypełnia stos wywołań ponieważ przypisanie wywołuje setter rekurencyjnie. Apparenly innerHTML jest już przeciążoną własnością w IE8 i można po prostu zapisać starszą parę get/set i użyć jej wewnątrz nowego deskryptora właściwości. Zrobione z MSDN:

var innerHTMLdescriptor = Object.getOwnPropertyDescriptor(Element.prototype, 'innerHTML'); 
Object.defineProperty(Element.prototype, 'innerHTML', 
    { set: function(htmlVal) { 
     var safeHTML = toStaticHTML(htmlVal); 
     innerHTMLdescriptor.set.call(this, safeHTML); 
    } 
}); 

to jednak nie wydaje się być w przypadku Chrome, gdzie getOwnPropertyDescriptor powraca niezdefiniowane innerHTML. W takim przypadku, w jaki sposób uzyskać dostęp do podstawowej usługi?

Dodatkowe pytanie: w jaki sposób zapewnić, że wszystkie obiekty utworzone w przyszłości będą miały specjalne zachowanie w postaci innerHTML? Czy można w tym celu użyć prototypów DOM? Wydaje się, że przeciążenie funkcji nie jest tym, czego potrzebuję. Być może możliwe jest przeciążenie konstruktora DOM i dodanie wywołania __defineGetter__/defineProperty, ale wygląda na to, że obsługa konstruktorów nie jest powszechna, więc chciałbym się dowiedzieć, czy jest jakaś alternatywa.

+0

Nie używaj \ _ \ _ defineSetter \ _ \ _ w aktualnym kodzie produkcji - jest to niestandardowe i może wykluczać użytkowników wielu przeglądarek. – Ryan

+1

Standardowy odpowiednik to "defineProperty' right? jednak problem odniesień do ukrytej własności istnieje ... – BruceBerry

+1

Nie, wciąż nie jest to normą. Nie powinieneś go używać, ponieważ wyklucza starsze przeglądarki. Oczywiście, jeśli robisz coś nieistotnego i pogarsza się z gracją, to jest OK. Ale wygląda na to, że nie będzie w twoim przypadku. – Ryan

Odpowiedz

1

Wszystko, czego potrzebujesz, to osobna właściwość składnicy danych do przechowywania rzeczywistej wartości, podobnie jak w innych językach używających modułów pobierających i ustawiających. Możesz użyć zamknięć, aby je ukryć.

var _innerHTML = ""; 

this.__defineSetter__("innerHTML", 
    function (val) { 
     alert("Setting to: " + val); 
     _innerHTML = val; 
    }); 

this.__defineGetter__("innerHTML", 
    function() { 
     return _innerHTML; 
    }); 

jednak odkryłem, że przy użyciu pobierające i ustawiające na istniejących właściwości DOM często po prostu nie będzie działać, dzięki specjalnej obsługi tych właściwości wewnętrznie. Na przykład nie będzie działać z właściwością value tekstu input. Spodziewałbym się, że innerHTML będzie na tej samej łodzi.

Powiązane problemy