2011-05-23 8 views
5

Estoy tratando de definir un setter personalizado para la propiedad innerHTML. Por desgracia, no estoy en condiciones de acceder a la propiedad subyacente después de que definir la función setter:Accediendo a propiedades ocultas por __defineGetter __/__ defineSetter__ en JavaScript

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

Este fragmento de código llena la pila de llamadas debido a que la asignación de llamadas de la incubadora de forma recursiva. Aparentemente innerHTML ya es una propiedad sobrecargada en IE8 y puede simplemente guardar el par get/set anterior y usarlo dentro del nuevo descriptor de propiedad. Tomado de 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); 
    } 
}); 

Sin embargo, esto no parece ser el caso para Chrome, donde getOwnPropertyDescriptor devuelve undefined para innerHTML. En este caso, ¿cómo accedo a la propiedad subyacente?

Pregunta extra: cómo me aseguro de que todos los objetos creados en el futuro tengan este comportamiento especial innerHTML? ¿Es posible usar prototipos DOM para esto? Parece que sobrecargar una función no es lo que necesito aquí. Quizás es posible sobrecargar el constructor DOM y agregar una llamada al __defineGetter__/defineProperty, pero parece que el soporte para constructores no es común, por lo que me gustaría saber si hay alguna alternativa.

+0

No use \ _ \ _ defineSetter \ _ \ _ en el código de producción real: no es estándar y puede excluir a los usuarios de muchos navegadores. – Ryan

+1

el equivalente estándar es 'defineProperty' ¿verdad? aún así, el problema de hacer referencia a lo oculto de la propiedad existe ... – BruceBerry

+1

No, todavía no es realmente un estándar. No debe usarlo porque excluye navegadores antiguos. Por supuesto, si estás haciendo algo que no es crucial y se degrada graciosamente, está bien. Pero no luce como lo hará en tu caso. – Ryan

Respuesta

1

Todo lo que necesita es una propiedad de almacén de datos independiente para almacenar el valor real, al igual que con otros lenguajes que usan getters y setters. Puedes usar cierres para hacerlos ocultos.

var _innerHTML = ""; 

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

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

Sin embargo, he encontrado que el uso de captadores y definidores de propiedades DOM existentes a menudo simplemente no funcionará, debido al manejo especial de estas propiedades internamente. Por ejemplo, no funcionará con la propiedad value de un texto input. Esperaría que innerHTML esté en el mismo barco.

Cuestiones relacionadas