2009-02-26 3 views
7

Ich kochte ein Muster, um HTML-Elemente zu erstellen und zu erweitern, die ihren Prototyp verwenden. Dies funktioniert wie ein Zauber in Nicht-IE-Browsern. Beispielcode kann gefunden werden @jsbin (siehe Seitenquelle)Gibt es wirklich keine Möglichkeit, den Prototyp eines HTML-Elements in IE (<8) zu offenbaren?

Der Vorteil dieses Musters sollte Geschwindigkeit sein (die Methoden sind in der Elementprototypenkette, so dass sie einmal referenziert werden). Du hast richtig geraten: IE no go. In IE < 8 ist der Prototyp von HTML-Elementen versteckt/nicht zugänglich, so dass Sie für jedes von Ihnen erstellte Element erneut auf die Nicht-Standardmethoden verweisen müssen (wodurch Sie viele Hinweise erhalten, wenn Sie das Muster intensiv verwenden). Ich habe das Internet nach Lösungen durchsucht, aber nur komplexe Workarounds gefunden. Gibt es wirklich keine Möglichkeit, auf einen HTML-Elemente-Prototyp in IE zuzugreifen?

+0

ist der Prototyp von HTML-Elementen in IE8? Wenn ja, wie wird darauf zugegriffen? – Helephant

+0

Es ist, soweit ich verstanden habe. Und es wird über den Prototyp zugegriffen (wie document.getElementById ('irgendeinelement'). Prototyp). In der Zwischenzeit habe ich einen DOM-Wrapper geschrieben, um leak free javascript verwenden zu können. – KooiInc

+0

@Helephant Ja, es ist zugänglich. Sie können zum Beispiel auf "Element.prototype" zugreifen und Methoden hinzufügen. Dies wird durch die neueste Version des [DOM Living Standard] (https://dom.spec.whatwg.org/) garantiert, die Dinge wie "Element" als [WebIDL] definiert (http://www.w3.org)/TR/WebIDL) Schnittstellen, die die explizite Implikation mit sich bringen, dass sie im globalen Umfang zugänglich sein sollten und ihre Prototypen modifizierbar sein sollten. –

Antwort

12

Nein, noch ist es garantiert, dass Sie mit Prototypen von DOM-Objekten in JavaScript im Allgemeinen herumhantieren können. Die DOM-Objekte sind nicht Teil der ECMAScript-Spezifikation; Sie sind möglicherweise nicht (und traditionell nicht) native JavaScript-Objekte in jedem Browser.

Dies ist der Grund, warum Frameworks ihre eigenen Container-Wrapper-Klassen haben.

Auch können Sie sich nicht auf 't.el.constructor' verlassen, selbst wenn es sich um native JS-Objekte handelte. "Konstruktor" ist keine Standardeigenschaft, ist in IE nicht verfügbar, und selbst in Mozilla tut er nicht, was Sie vielleicht denken. Vermeiden.

+0

Vieles davon ist veraltet, und ich bin mir nicht sicher, ob es auch nur gepostet wurde. Sowohl der alte [DOM Level 3] (http://www.w3.org/TR/DOM-Level-3-Core/ecma-script-binding.html) und der aktuelle [DOM Living Standard] (http: // www .w3.org/TR/dom /) explizit auf * constructors * verweisen, wenn Schnittstellen angegeben werden, und das [ECMAScript 3] (http://www.ecma-international.org/publications/files/ECMA-ST-ARCH/ ECMA-262,% 203rd% 20edition,% 20December% 201999.pdf) (siehe Abschnitt 4.2.1) und [ECMAScript 5] (http://www.ecma-international.org/ecma-262/5.1/#sec 4.3.4) Spezifikationen schreiben vor, dass ein Konstruktor eine "Prototyp" -Eigenschaft hat. –

+0

Darüber hinaus wurde die Konstruktoreigenschaft * für native Objekte in ECMAScript 3 angegeben. CTRL-F für '.constructor' oder' constructor property' in http://www.ecma-international.org/publications/files/ECMA-ST-ARCH/ECMA-262,%203rd%20edition,%20December%201999 .pdf. Sie bleiben in ECMAScript 5 angegeben. Es scheint jedoch wahr zu sein, dass es keine allgemeine Regel gibt, dass die 'Prototyp'-Eigenschaft eines Konstruktors eine 'constructor'-Eigenschaft haben muss, die auf den Konstruktor zurück zeigt 'Konstruktor'-Eigenschaft ohne technisch zu verletzen, aber in der Praxis nicht. –

+0

Zusätzlich wird in der neuesten Version des [DOM Living Standard] (http://www.w3.org/TR/dom/) garantiert, dass sich alle DOM-Objekte sinnvoll verhalten, da sie mit [WebIDL] deklariert werden (http://www.w3.org/TR/WebIDL), die unter anderem vorschreibt, dass ein Interface-Objekt als eine Eigenschaft des globalen Objekts existieren muss, es sei denn, "NoInterfaceObject" ist angegeben, und diese Prototyp-Objekte müssen 'constructor haben 'Eigenschaften, die auf das Schnittstellenobjekt zeigen. Also, was kleine spek-Ambiguität blieb im Jahr 2009 und jetzt aufgeräumt. –

4

Ja, es gibt wirklich keine Möglichkeit, dies zu tun.

IE-Elemente basieren auf COM-Objekten, die es eigentlich nicht erlauben, willkürliche Mitglieder zu ihren Schnittstellen hinzuzufügen (in COM sind Schnittstellen ein Vertrag und sollten sich niemals ändern). Die Implementierung dieser Schnittstellen kann nicht durch Javascript erweitert werden, die Elemente sind einfach nicht prototypisch.

IE fügt eine spezielle Schnittstelle hinzu, die entworfen wurde, um mit Javascript zu arbeiten, um das Hinzufügen neuer Mitglieder zu einer bestimmten Instanz zu erlauben, aber kein neues Mitglied zu 'Klasse' hinzuzufügen, da es keinen Prototyp gibt.

0

Die folgenden, ausgeschnitten und eingefügt aus dem Artikel HTMLElement doesnt work in IE. Beispiele funktionieren perfekt in IE und 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> 

Probieren Sie es Grüße

+3

Verwenden Sie nicht den Teufel 'eval' !!!!! Zum Beispiel, anstelle von 'eval (" _ elem. "+ Name +" = fn ");' benutzen '_elem [name] = fn;' – Oriol

Verwandte Themen