专栏首页游戏杂谈JavaScript的类型错误:Illegal invocation

JavaScript的类型错误:Illegal invocation

今天写一个十分简单的页面,要获取页面中某一DOM,用了如下的写法:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"> <head>  <title> new document </title>  <meta name="generator" content="editplus" />  <meta name="author" content="" />  <meta name="keywords" content="" />  <meta name="description" content="" />  <meta http-equiv="content-type" content="text/html;charset=utf-8" /> </head>  <body>  <div id="demo">demo</div>    <script type='text/javascript'>   1:     2:         var d = document.getElementById;   3:     4:         var s = d("demo").innerHTML;   5:            6:         alert(s);   7:     </script> </body></html>

昨一看好像也没什么问题,在IE6~8下运行也没有任何的问题,可是在其它浏览器下就报错了,报了这样一个错:

Uncaught TypeError: Illegal invocation    未捕获的类型错误:非法调用

当时没太注意,当时没仔细去弄清楚是怎么回事,然后在微博中发一条消息,稍作了一下记录。等吃完饭回来看到有一条回复,是taibo转播的,说明了原因:call/apply 上下文非法时,会抛出此异常,IE9也遵守此规范。后面是可以避免报此错误的一个example,我一看没太注意,之后他又发了一个ref

Calling a Method with a Function Pointer without ".call" or ".bind"

看完以后才真正缓过神来,上面的在IE9和非IE(例如Chrome)浏览器下的写法如同:

<script type='text/javascript'>        var d = document.getElementById;                var s = d.call(window, "demo").innerHTML                alert(s);    </script>

这样写显然会导致调用错误,因为id为demo的DOM元素应该是在document对象中,而不是在其它对象中。改为调用document就可以得到想要的结果:

<script type='text/javascript'>        var d = document.getElementById;                var s = d.call(document, "demo").innerHTML                alert(s);    </script>

但是在我的IE6下却报错了,然后我开始找原因了…

我试图去循环迭代出d中的所有属性

var d = document.getElementById;        for (var p in d){}

但得到的情况很糟糕,不知道是我的系统问题,还是确实存在这个问题,运行后直接出现了“"0x7e2cf10c" 指令引用的 "0x00000000" 内存。该内存不能为 "read"。 ”

之后我尝试着使用typeof,想看看它到底是个什么东东,按我的预期,它应该是一个函数,只有函数才能被调用“()”

var d = document.getElementById;        alert(typeof d);

在我的IE6中得到的结果让我很失望“object”,好在Chrome下得到的是 “function”。也许你觉得上面的typeof可能不准,那使用下面的方法应该是没什么异议了吧

alert(Object.prototype.toString.call(d));  结果依旧表明:ie下为object而Chrome则为function

最为神奇的是在我的ie6下,d是没有toString方法的,我想它应该是一个很“干净”的对象吧(没有toString、valueOf方法),而Chrome是符合预期的

更重要的是它不Function的实例,更不是Object的实例,而在Chrome下也符合预期。

var d = document.getElementById;        alert(d instanceof Function);alert(d instanceof Object);

它到底如何实现的呢?如果是Global对象下的方法,如parseInt、isNaN等,它应该可以被删除,很明显的它属于docuemnt对象下的方法而不是Global下的方法。至于它到底怎么实现的,我暂时还不太清楚,只是觉得一个对象 object(要么它的typeof有问题),也可以被调用,这个就很神奇了。

()在javascript虽然有多义性,但无非下面几种:

1、函数声明时的函数列表 例:function fnName(arg1, arg2) {};

2、和一些语句一起使用用来限定的作用,例:for()、while()等:

3、和new一起使用,用来传递参数--在不传递参数的情况下()可以省略,但并不建议  例:var obj1 = new FunName();

4、计算一个表达式,提升运算的优先级 例:var  a = 5 * (3 + 4)

5、正则表达中用作捕获的分组之用

6、函数调用符

上面的问题让我困惑的是,一个object如何被调用,这里的()肯定是函数调用符,那么document.getElementById应该是一个函数才对,而实际得到的结果却不是(还是这个测试类型得到的结果有问题?!)

需要说明一下情况的是,最初写的页面不是在宿舍写的,用的浏览器是IE8,而我回宿舍之后本本上装的是IE6(为了测试之用,虽然我很痛恨ie6),其它浏览器暂时没全部测试过。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • as3+php上传图片的三种方式

    1)设置FlashDevelop使用flash player10(debug版本,因为有一个demo使用了本地预览)

    meteoric
  • 使用nginx反向代理获取百度MP3的真实网址

    在没有自己的音乐搜索引擎的时候,却又想让用户可以较为方便的在自己的网站上搜索网络歌曲,在这里使用的是百度的MP3~

    meteoric
  • createEventObject 与 createEvent EDIT WATCH

    jQuery中有很好用的trigger来触发事件,但总不能写什么都去引入jQuery吧

    meteoric
  • JavaScript学习笔记

    【如果大家对程序员,web前端感兴趣,想要学习的,关注一下小编吧。加群:731771211。免费赠送web前端系统的学习资料!!前端学习必备公众号ID:mtbc...

    一墨编程学习
  • ol中闪烁点动画的实现

    实现如图的动画,可以用两种思路: 1.overlay+css3动画实现; 2.canvas动画实现。

    lzugis
  • 测试控制鼠标的技巧

    <script type="text/javascript"> var total = 0 var play = false function display(...

    似水的流年
  • Arcgis for Js之加载wms服务

    概述:本节讲述Arcgis for Js加载ArcgisServer和GeoServer发布的wms服务。

    lzugis
  • 全民刷军装背后的AI技术及简单实现

    昨天有Design-AI-Lab用户后台留言,问为什么换军装的h5这么火,但没见到有技术文章分析如何实现。 我回复说,大概是比较简单吧,主要工作是图像合成。 ...

    mixlab
  • unwx:一个解压微信小程序的命令 、微信小程序是如何压缩的

    两个月前在写一系列的微信小程序的文章时,写了一个库,用来解压微信小程序的——当时想的是等着公测了,来试试看能不能解压开别人的代码。然后再做个兼容小程序的框架,再...

    Phodal
  • Javascript快速入门(上篇)

    Javascript的熟练之路,小弟来了。 ? JavaScript简介:JavaScript一种直译式脚本语言,是一种动态类型、弱类型、基于原型的语言,...

    用户1216676

扫码关注云+社区

领取腾讯云代金券