2016-06-06 3 views
9

Мне было интересно, когда работал с chrome devtools. Но, похоже, тип <object> является «функцией».
Я не нашел никаких объяснений или ссылок.Почему тип <object> является функцией?

Вот простой пример: https://jsfiddle.net/fez34zbf/
HTML:

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

JS:

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

результаты консоли будут:

function 
object 

Любые идеи?

+0

Я думаю, что вопрос, * какой тип функции является 'экземпляр HTMLObjectElement'? * – Pointy

+0

Это было предложено до : http: // stackoverflow. com/questions/13873684/firefox-17-reports-created-dom-element-htmlobjectelement-as-function-when-usin, но ответ Тилла кажется более обширным. –

ответ

4

Как уже упоминалось, типof должен возвращать "function" для всех объектов, которые имеют внутренний метод [[Call]]. (spec). Так что интересная часть состоит в том, что экземпляры HTMLObjectElement по какой-то причине имеют внутренний метод [[Call]].

Об этом сообщают об ошибках firefox, а также chrome. Пока нет ответов на вопрос FireFox на хромированной вопросе есть объяснение, где [[Call]] добавляется к HTMLObjectElement

Да, это правильно. SetCallAsFunctionHandler() делает объект вызываемым в соответствии с EcmaScript, поэтому мы должны вернуть «функцию» для typeof.

SetCallAsFunctionHandler, похоже, некоторые детали реализации в версии 8. В соответствии с проблемой хром использовал отчет object как typeof экземпляров HTMLObjectElement, но они изменили его совместимость с firefox.


Теперь почему существует [[Call]] внутренний метод на HTMLObjectElement? Поскольку this stackoverflow answer подразумевает, что это, по-видимому, используется некоторыми плагинами. HTMLObjectElement используется плагинами (например, вспышкой). И некоторые из этих плагинов, вероятно, исключают ввод с использованием этой функции.

Глядя на sourcecode хрома, кажется, некоторый код, который действительно обрабатывает некоторые унаследованные перезвонить (V8HTMLEmbedElement.cpp и V8HTMLPlugInElementCustom.cpp).

Также в this FireFox билет это подтверждается

почему на земле Встраивание элементов/объектов с правом отзыва в первую очередь? [...] Насколько это возможно, поскольку некоторые плагины делают что-то, когда вы их называете, и никто не хочет нарушать это по соображениям совместимости ...

Я не нашёл ни одной спецификации, определяющей эту функцию. Html5 спецификации упоминает legacy caller operation, но не определяет, как именно он работает

Так как резюме: typeof document.createElement('object')"function" это потому, что она имеет внутренний метод [[Call]]. И он имеет внутренний метод [[Call]] из-за унаследованных причин.


Если выполнить этот код в хроме

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

вы получаете undefined в качестве возвращаемого значения. Если выполнить его в светлячок вы получите исключение

компонент не доступен»nsresult: "0x80040111 (NS_ERROR_NOT_AVAILABLE)" Location: "рамка :: отладчик Eval кода :: :: строки 1" данные JS: нет

Интересно document.createElement('object') instanceof Function является false и, таким образом, ни один из методов из Function.prototype не существуют на HTMLObjectElement.

+1

Большой углубленный ответ – alex

+0

Очень ясно, спасибо – Deliaz

1

Как указано в https://es5.github.io/x11.html#x11.4.3, HTMLObjectElement (HTMLEmbedElement также) имеет внутреннее свойство [[Call]]. typeof проверяет это свойство, чтобы вернуть "function", что я согласен с тобой довольно неожиданно.

+1

Почему у него есть свойство '[[Call]]'? – BoltKey

Смежные вопросы