zoukankan      html  css  js  c++  java
  • 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"。 ”

    R4ORJAQV1EO~)CGF}AT(`{E

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

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

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

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

    image      image

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

    image   image

    更重要的是它不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),其它浏览器暂时没全部测试过。

  • 相关阅读:
    如何通过命令行窗口查看sqlite数据库文件
    eclipse自动补全的设置
    文本装饰
    注释和特殊符号
    文本装饰
    网页背景
    通过ArcGIS Server admin 查看和删除已注册的 Web Adaptor
    通过 ArcGIS Server Manager 查看已安装的 Web Adaptor
    通过 ArcGIS Server Manager 验证 DataStore
    Windows上安装ArcGIS Enterprise——以 Windows Server 2012 R2上安装 ArcGIS 10.8为例
  • 原文地址:https://www.cnblogs.com/meteoric_cry/p/2026582.html
Copyright © 2011-2022 走看看