2009-02-26 8 views
7

He cocinado un patrón para crear y extender elementos html utilizando su prototipo. Esto funciona como un encanto en navegadores que no sean. El código de ejemplo se puede encontrar en jsbin (ver fuente de página)¿Realmente no hay forma de exponer el prototipo de un elemento html en IE (<8)?

La ventaja de este patrón debe ser la velocidad (los métodos están en la cadena de prototipos de elementos, por lo que se hace referencia a ellos una vez). Has acertado: IE no ir. En IE < 8 el prototipo de elementos html está oculto/no accesible, por lo que para cada elemento que cree, debe volver a hacer referencia a los métodos no estándar (dejándole muchos punteros si usa el patrón de forma intensiva). Busqué soluciones en la web, pero solo encontré soluciones complejas. ¿Hay realmente forma de acceder a un prototipo de elementos HTML en IE?

+0

es el prototipo de los elementos HTML disponible en Internet Explorer 8? Si es así, ¿cómo se accede? – Helephant

+0

Es, por lo que yo entendí. Y se accede a través del prototipo (como document.getElementById ('someelement'). Prototype). Mientras tanto, escribí un DOM-wrapper para poder usar Javascript sin fugas. – KooiInc

+0

@Helephant Sí, es accesible. Puede acceder, por ejemplo, a 'Element.prototype' y agregarle métodos. Esto está garantizado por la última versión del [Estándar de vida DOM] (https://dom.spec.whatwg.org/), que define cosas como 'Element' como [WebIDL] (http://www.w3.org/TR/WebIDL), lo que conlleva la implicación explícita de que deberían ser accesibles en el ámbito global y sus prototipos deberían ser modificables. –

Respuesta

12

No, ni se garantiza que pueda jugar con prototipos de objetos DOM en JavaScript en general. Los objetos DOM no son parte de la especificación ECMAScript; es posible que no sean (y tradicionalmente no lo sean) objetos JavaScript nativos, en ningún navegador.

Es por eso que los frameworks tienden a tener sus propias clases de contenedor 'contenedor'.

También no puede confiar en 't.el.constructor' incluso si fueran objetos JS nativos. 'Constructor' no es una propiedad estándar, no está disponible en IE, e incluso en Mozilla no hace lo que crees que es. Evitar.

+0

Mucho de esto es obsoleto, y no estoy seguro de que sea cierto ni siquiera cuando se publique. Tanto el antiguo [DOM Level 3] (http://www.w3.org/TR/DOM-Level-3-Core/ecma-script-binding.html) como el actual [DOM Living Standard] (http: // www. .w3.org/TR/dom /) hace referencia explícita a * constructores * al especificar interfaces, y [ECMAScript 3] (http://www.ecma-international.org/publications/files/ECMA-ST-ARCH/ ECMA-262,% 203rd% 20edition,% 20December% 201999.pdf) (ver sección 4.2.1) y [ECMAScript 5] (http://www.ecma-international.org/ecma-262/5.1/#sec- 4.3.4) las especificaciones dictan que un constructor tiene una propiedad 'prototype'. –

+0

Además, la propiedad del constructor * fue * especificada para objetos nativos en ECMAScript 3; solo CTRL-F para '.constructor' o' propiedad del constructor' en http://www.ecma-international.org/publications/files/ECMA-ST-ARCH/ECMA-262,%203rd%20edition,%20December%201999 .pdf. Siguen especificados en ECMAScript 5. Sin embargo, parece * verdad, que no existe una regla general que la propiedad 'prototipo' de un constructor deba tener una propiedad' constructor' que apunte al constructor, por lo que creo que los objetos host podrían tener una tontería 'constructor' sin violar técnicamente la especificación, pero en la práctica no es así. –

+0

Además, en la última versión del [Estándar de vida DOM] (http://www.w3.org/TR/dom/), todos los objetos DOM están garantizados para comportarse con sensatez, ya que se declaran utilizando [WebIDL] (http://www.w3.org/TR/WebIDL), que dicta, entre otras cosas, que un objeto de interfaz debe existir como una propiedad del objeto global a menos que se especifique 'NoInterfaceObject', y que los objetos prototipo deben tener' constructor 'propiedades que apuntan al objeto de interfaz. Entonces, ¿qué poca ambigüedad de especificación se mantuvo en 2009 y ahora se arregló? –

4

Sí, realmente no hay forma de hacerlo.

Los elementos IE se basan en objetos COM que en realidad no permiten agregar miembros arbitrarios a sus interfaces (en COM, las interfaces son un contrato y nunca deberían cambiar). La implementación de estas interfaces no puede ser extendida por Javascript, los elementos simplemente no son prototípicos.

IE agrega una interfaz especial diseñada para trabajar con Javascript para permitir la adición de nuevos miembros a una instancia específica pero no se puede agregar un nuevo miembro a 'clase' ya que no hay ningún prototipo con el que jugar.

0

Lo siguiente, cortado y pegado del artículo HTMLElement doesnt work in IE. Los ejemplos funcionan perfectamente en IE y Firefox.

<html> 
<head> 
    <script type="text/javascript" src="DOMElement.js"></script> 
    <script type="text/javascript"> 

     var DOMElement = 
     { 
      extend: function(name,fn) 
      { 
       if(!document.all) 
        eval("HTMLElement.prototype." + name + " = fn"); 
       else 
       { 
        // 
        // IE doesn't allow access to HTMLElement 
        // so we need to override 
        // *document.createElement 
        // *document.getElementById 
        // *document.getElementsByTagName 
        // 

        //take a copy of 
        //document.createElement 
        var _createElement = document.createElement; 

        //override document.createElement 
        document.createElement = function(tag) 
        { 
         var _elem = _createElement(tag); 
         eval("_elem." + name + " = fn"); 
         return _elem; 
        } 

        //take copy of 
        //document.getElementById 
        var _getElementById = document.getElementById; 

        //override document.getElementById 
        document.getElementById = function(id) 
        { 
         var _elem = _getElementById(id); 
         eval("_elem." + name + " = fn"); 
         return _elem; 
        } 

        //take copy of 
        //document.getElementsByTagName 
        var _getElementsByTagName = document.getElementsByTagName; 

        //override document.getElementsByTagName 
        document.getElementsByTagName = function(tag) 
        { 
         var _arr = _getElementsByTagName(tag); 
         for(var _elem=0;_elem<_arr.length;_elem++) 
          eval("_arr[_elem]." + name + " = fn"); 
         return _arr; 
        } 
       } 
      } 
     }; 

     DOMElement.extend("foo",function(){alert('bar')}); 
     DOMElement.extend("about","DOMElement v0.1") 
     DOMElement.extend("contents",function(){return this.innerHTML}) 
     var elem = document.createElement("div"); 
     elem.foo(); 

     onload = function() 
     { 
      var elem2 = document.getElementById("myDiv"); 
      alert(elem2.about); 

      var divs = document.getElementsByTagName("div"); 
      for(var i=0;i<divs.length;i++) 
       alert(divs[i].contents()) 
     } 

    </script> 
</head> 
<body> 

    <div id="myDiv">hi</div> 
    <div id="div2">there</div> 

</body> 
</html> 

probarlo Saludos

+3

No use el diablo 'eval' !!!!! Por ejemplo, en lugar de 'eval (" _ elem. "+ Nombre +" = fn ");' use '_elem [nombre] = fn;' – Oriol

Cuestiones relacionadas