JavaScript的类型错误:Illegalinvocation
今天写⼀个⼗分简单的页⾯,要获取页⾯中某⼀DOM,⽤了如下的写法:
<!DOCTYPE html PUBLIC"-//W3C//DTD XHTML 1.0 Transitional//EN""/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="/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 = ElementById;
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
看完以后才真正缓过神来,上⾯的在IE9和⾮IE(例如Chrome)浏览器下的写法如同:
<script type='text/javascript'>
var d = ElementById;
var s = d.call(window, "demo").innerHTML
alert(s);
</script>
这样写显然会导致调⽤错误,因为id为demo的DOM元素应该是在document对象中,⽽不是在其它对象中。改为调⽤document就可以得到想要的结果:
<script type='text/javascript'>
var d = ElementById;
var s = d.call(document, "demo").innerHTML
alert(s);
</script>
但是在我的IE6下却报错了,然后我开始原因了…
我试图去循环迭代出d中的所有属性
var d = ElementById;
for (var p in d){}
但得到的情况很糟糕,不知道是我的系统问题,还是确实存在这个问题,运⾏后直接出现了“"0x7e2cf10c" 指令引⽤的 "0x00000000" 内存。该内存不能为 "read"。 ”
之后我尝试着使⽤typeof,想看看它到底是个什么东东,按我的预期,它应该是⼀个函数,只有函数才能被调⽤“()”
var d = ElementById;
alert(typeof d);
在我的IE6中得到的结果让我很失望“object”,好在Chrome下得到的是 “function”。也许你觉得上⾯的typeof可能不准,那使⽤下⾯的⽅法应该是没什么异议了吧
alert(String.call(d)); 结果依旧表明:ie下为object⽽Chrome则为function
最为神奇的是在我的ie6下,d是没有toString⽅法的,我想它应该是⼀个很“⼲净”的对象吧(没有toString、valueOf⽅法),⽽Chrome是符合预期的
更重要的是它不Function的实例,更不是Object的实例,⽽在Chrome下也符合预期。
var d = ElementById;
alert(d instanceof Function);
alert(d instanceof Object);
它到底如何实现的呢?如果是Global对象下的⽅法,如parseInt、isNaN等,它应该可以被删除,很明显的它属于docuemnt对象下的⽅法⽽不是Global下的⽅法。⾄于它到底怎么实现的,我暂时还不太清楚,只是觉得⼀个对象 object(要么它的typeof有问题),也可以被调⽤,这个就很神奇了。
()在javascript虽然有多义性,但⽆⾮下⾯⼏种:
html document是什么1、函数声明时的函数列表例:function fnName(arg1, arg2) {};
2、和⼀些语句⼀起使⽤⽤来限定的作⽤,例:for()、while()等:
3、和new⼀起使⽤,⽤来传递参数--在不传递参数的情况下()可以省略,但并不建议例:var obj1 = new FunName();
4、计算⼀个表达式,提升运算的优先级例:var a = 5 * (3 + 4)
5、正则表达中⽤作捕获的分组之⽤
6、函数调⽤符
上⾯的问题让我困惑的是,⼀个object如何被调⽤,这⾥的()肯定是函数调⽤符,那么ElementById应该是⼀个函数才对,⽽实际得到的结果却不是(还是这个测试类型得到的结果有问题?!)
需要说明⼀下情况的是,最初写的页⾯不是在宿舍写的,⽤的浏览器是IE8,⽽我回宿舍之后本本上装的是IE6(为了测试之⽤,虽然我很痛恨ie6),其它浏览器暂时没全部测试过。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论