2011-05-23 12 views
5

Sto cercando di definire un setter personalizzato per la proprietà innerHTML. Purtroppo, non sono in grado di accedere alla proprietà sottostante dopo definisco la funzione setter:proprietà Accesso nascosti da __defineGetter __/__ defineSetter__ in JavaScript

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

Questo frammento riempie lo stack di chiamate poiché la cessione chiama il setter ricorsivamente. Apparenly innerHTML è già una proprietà sovraccarico in IE8 e si può semplicemente salvare il get coppia di anziani/impostare e utilizzare all'interno del nuovo descrittore di proprietà. Tratto da 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); 
    } 
}); 

Tuttavia, questo non sembra essere il caso per Chrome, dove getOwnPropertyDescriptor ritorna undefined per innerHTML. In questo caso, come posso accedere alla proprietà sottostante?

Domanda bonus: come faccio a garantire che tutti gli oggetti creati in futuro hanno questa speciale innerHTML comportamento? È possibile utilizzare i prototipi DOM per questo? Sembra che sovraccaricare una funzione non sia ciò di cui ho bisogno qui. Forse è possibile sovraccaricare il costruttore DOM e aggiungere una chiamata __defineGetter__/defineProperty ma sembra che il supporto per i costruttori non è comune, così mi piacerebbe sapere se c'è qualche alternativa.

+0

Non usare \ _ \ _ defineSetter \ _ \ _ nel codice di produzione vero e proprio - è non standard e può escludere gli utenti di molti browser. – Ryan

+1

l'equivalente standard è 'defineProperty' giusto? ancora, il problema di referenziare la proprietà nascosta esiste ... – BruceBerry

+1

No, non è ancora uno standard. Non dovresti usarlo perché esclude i browser più vecchi. Certo, se stai facendo qualcosa di non cruciale e si degrada con grazia, va bene. Ma non sembra che sarà nel tuo caso. – Ryan

risposta

1

Tutto ciò che serve è una proprietà datastore separata per memorizzare il valore reale, proprio come con altre lingue che usano getter e setter. Puoi usare chiusure per renderle nascoste.

var _innerHTML = ""; 

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

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

Tuttavia, ho trovato che l'uso di getter e setter sulle proprietà DOM esistenti spesso semplicemente non funzionerà, a causa della gestione speciale di queste proprietà internamente. Ad esempio, non funzionerà con la proprietà value di un testo input. Mi aspetto che lo innerHTML sia nella stessa barca.