2016-06-06 3 views
9

Ich wunderte mich, als ich mit Chrom Devtools arbeitete. Aber es scheint, dass der Typ <object> eine "Funktion" ist.
Ich habe keine Erklärung oder Referenzen gefunden. HierWarum ist der Typ <object> eine Funktion?

ist das einfache Beispiel: https://jsfiddle.net/fez34zbf/
HTML:

<object></object> 
<video></video> 

JS:

console.log(typeof document.querySelector('object')); 
console.log(typeof document.querySelector('video')); 

Konsole Ergebnisse werden:

function 
object 

Irgendwelche Ideen?

+0

ich denke, die Frage ist, * welche Art von Funktion ist eine 'HTMLObjectElement' Instanz? * – Pointy

+0

Dies wird vor gefragt worden, : http: // Stapelüberlauf. com/questions/13873684/firefox-17-reports-erstellt-dom-element-htmlobjectelement-as-function-wenn-usin, aber Tills Antwort scheint umfangreicher. –

Antwort

4

Wie bereits erwähnt, muss typeof "function" für alle Objekte zurückgeben, die eine interne Methode [[Call]] haben (spec). So ist der interessante Teil, dass Instanzen von HTMLObjectElement aus irgendeinem Grund eine interne Methode [[Call]] haben.

Es gibt Fehlerberichte hierzu für firefox sowie chrome. Zwar gibt es keine Antworten auf dem firefox Thema auf dem Chrom Problem gibt es eine Erklärung, wo [[Call]] zu HTMLObjectElement

Ja hinzugefügt wird, das ist richtig. SetCallAsFunctionHandler() macht das Objekt gemäß EcmaScript aufrufbar, daher müssen wir "function" für typeof zurückgeben.

SetCallAsFunctionHandler scheint einige Implementierungsdetails in V8 zu sein. Laut der Ausgabe Chrom verwendet, um object als die typeof Instanzen von HTMLObjectElement zu melden, aber sie änderte es mit Firefox kompatibel zu sein.


Nun, warum gibt es eine [[Call]] interne Methode auf HTMLObjectElement? Wie this stackoverflow answer impliziert, scheint dies von einigen Plugins verwendet zu werden. HTMLObjectElement wird von Plugins (z. B. Flash) verwendet. Und einige dieser Plugins wahrscheinlich außer Eingabe mit dieser Funktion.

Mit Blick auf die sourcecode von Chrom scheint es einige Code zu sein, die in der Tat einige Legacy-Anruf behandelt zurück (V8HTMLEmbedElement.cpp und V8HTMLPlugInElementCustom.cpp).

Auch in this firefox Ticket dies

bestätigt

warum auf der Erde ist Einbetten/Objektelemente aufrufbar in erster Linie? [...] Soweit das irgendjemand sagen kann, weil manche Plug-Ins etwas machen, wenn man sie anruft und niemand das aus Kompatibilitätsgründen kaputt machen will ...

Ich habe keine Spezifikation gefunden, die dieses Verhalten definiert. Die html5 spec erwähnt eine legacy caller operation aber nicht genau definieren, wie es funktioniert

So als Zusammenfassung: typeof document.createElement('object') ist "function", weil es eine [[Call]] interne Methode hat. Und es hat eine [[Call]] interne Methode aus Legacy-Gründen.


Wenn Sie diesen Code in Chrom ausführen

(function(){ 
    'use strict'; 
    return document.createElement('object')() 
})() 

Sie erhalten undefined als Rückgabewert. Wenn Sie es in Firefox ausführen erhalten Sie eine Ausnahme

Komponente nicht verfügbar“nsresult: "ist 0x80040111 (NS_ERROR_NOT_AVAILABLE)" Ort: "JS Rahmen :: Debugger eval Code :: :: Linie 1" Daten: nein

Interessanter document.createElement('object') instanceof Function ist false und somit keine der Methoden aus Function.prototype existiert auf HTMLObjectElement.

+1

Große eingehende Antwort – alex

+0

Sehr klar, danke – Deliaz

1

Wie in https://es5.github.io/x11.html#x11.4.3 angegeben, hat HTMLObjectElement (HTMLEMbedElement als auch) eine interne Eigenschaft [[Call]]. typeof prüft diese Eigenschaft, "function" zurückgeben, was ich stimme, ist zunächst ziemlich überraschend.

+1

Warum hat es die '[[Call]]' Eigenschaft? – BoltKey