为什么<object>的类型是一个函数?

时间:2016-06-06 12:21:53

标签: javascript html object tags

当我使用chrome devtools时,我很奇怪。 但似乎typeof <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

有什么想法吗?

2 个答案:

答案 0 :(得分:4)

正如已经提到的,对于所有具有"function"内部方法的对象,typeof必须返回[[Call]]。(spec)。所以有趣的是,由于某种原因,HTMLObjectElement的实例具有[[Call]]内部方法。

firefox以及chrome都有错误报告。虽然在Chrome问题上没有关于firefox问题的回复,但有[[Call]]添加到HTMLObjectElement的解释

  

是的,这是对的。 SetCallAsFunctionHandler()根据EcmaScript使对象可调用,因此我们必须返回&#34; function&#34;对于typeof。

SetCallAsFunctionHandler似乎是v8中的一些实现细节。根据问题chrome,用于报告object typeof HTMLObjectElement [[Call]]个实例,但他们将其更改为与Firefox兼容。

为什么HTMLObjectElement上有HTMLObjectElement内部方法?正如this stackoverflow answer暗示这似乎被某些插件使用。插件使用V8HTMLEmbedElement.cpp(例如flash)。其中一些插件可能除了使用此功能输入外。

查看Chrome的source code,似乎有一些代码确实处理了一些旧版回调(V8HTMLPlugInElementCustom.cpptypeof document.createElement('object'))。

同样在this firefox票证中确认

  

为什么地球上的Embed / Object元素首先可以调用? [...]据任何人都可以说,因为一些插件在你打电话时会做一些事情而没有人想因为比较而打破这个...

我没有找到任何定义此行为的规范。 html5规范提到legacy caller operation,但没有确切地定义它是如何工作的

所以摘要:"function"[[Call]]因为它有[[Call]]内部方法。由于遗留原因,它有一个(function(){ 'use strict'; return document.createElement('object')() })() 内部方法。

如果您在chrome中执行此代码

undefined

您获得document.createElement('object') instanceof Function作为返回值。如果你在firefox中执行它,你会得到一个例外

  

组件不可用&#34; nsresult:&#34; 0x80040111(NS_ERROR_NOT_AVAILABLE)&#34; location:&#34; JS frame :: debugger eval code :: :: line 1&#34;数据:没有

有趣的是,falseFunction.prototype,因此HTMLObjectElement中的public class getList extends AsyncTask<Void, String, String> { @Override protected void onPreExecute() { super.onPreExecute(); pDialog = new ProgressDialog(getActivity()); pDialog.setCancelable(false); pDialog.setMessage("Please wait..."); pDialog.setCanceledOnTouchOutside(false); pDialog.show(); } @Override protected String doInBackground(Void... params) { String text = null; JSONObject json; HttpClient httpclient = new DefaultHttpClient(); //Configuration.empcode.trim() HttpGet httppost = new HttpGet(ListURL+UserCode+"/"+indexNo); try { HttpResponse response = httpclient.execute(httppost); // for JSON: if (response != null) { InputStream is = response.getEntity().getContent(); BufferedReader reader = new BufferedReader( new InputStreamReader(is)); // String result = EntityUtils.toString((HttpEntity) // response); StringBuilder sb = new StringBuilder(); String line = null; try { while ((line = reader.readLine()) != null) { sb.append(line + "\n"); } } catch (IOException e) { e.printStackTrace(); } finally { try { is.close(); } catch (IOException e) { e.printStackTrace(); } } text = sb.toString(); } } catch (ClientProtocolException e) { // TODO Auto-generated catch block } catch (IOException e) { // TODO Auto-generated catch block } return text; } @Override protected void onPostExecute(String result) { pDialog.dismiss(); if(result!=null) { try { JSONObject resultObject = new JSONObject(result); JSONArray resultArray = resultObject.getJSONArray("Table"); for(int i =0;i<resultArray.length();i++) { JSONObject resultObjects = resultArray.getJSONObject(i); Code = resultObjects.getString("Code"); Title = resultObjects.getString("Title"); status= resultObjects.getString("status"); date= resultObjects.getString("date"); TitleList.add(Title); CodeList.add(Code); statusList.add(status); dateList.add(date); int count = db.getInProgressCount(CourseCode); if(count==0) { db.addInProgress(new InProgressTable(Code,Title,status,date)); } else { db.updateInProgress(new InProgressTable(Code,Title,status,date)); } } adapter = new CustomInProgressList(getActivity(),TitleList,CodeList,statusList,dateList); //adapter.setCustomButtonListner(Catalog_Activity.this); list.setAdapter(adapter); scrollMyListViewToBottom(resultArray.length()); int count = db.getAllInProgressCount(); if (adapter.getCount()<1 && count<1){ list.setVisibility(View.GONE); noRes.setVisibility(View.VISIBLE); }else { list.setVisibility(View.VISIBLE); noRes.setVisibility(View.GONE); } if (resultArray.length()<5); loadMore.setVisibility(View.GONE); } catch(Exception ex) { ex.printStackTrace(); } } else { AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); builder.setTitle("Alert"); builder.setMessage("Data is not available, Please try again later"); builder.setPositiveButton("OK", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { dialog.cancel(); } }); AlertDialog dialog = builder.create(); dialog.show(); } } } 中没有任何方法确实存在。

答案 1 :(得分:1)

https://es5.github.io/x11.html#x11.4.3中所述,HTMLObjectElement(HTMLEmbedElement)也具有[[Call]]内部属性。 typeof检查此属性以返回"function",我同意这一点非常令人惊讶。