• 一次由注释引发的“血案”


    有几天没写博客了,今天有点时间,正好把前几天遇到的一件“诡异”的问题记录一下。

    我是在前几天学习CSS时遇到这个问题的。当时看到某个网站有一个CSS效果不错,就想研究一下。由于代码很短,我不想将整个页面保存下来,所以我点击"查看源文件",找到这段代码并拷贝到测试页面中。

    它的主要部分是这样的:

    /*file设为透明,并覆盖整个触发面*/
    a.files input {
         margin-left:-350px;
         font-size:30px;
         cursor:pointer;
         filter:alpha(opacity=0);
         opacity:0;
    }

     
    用FF查看效果,一切正常。但当我换到IE后,问题来了,没有出现预期的效果!

    当然,大家看到这篇文章的标题可能就已经猜到大概原因是什么了。但当时于我却是一脸茫然(原网页在FF和IE下显示均正常)

    于是我开始分析……

    首先想到的是:

    是不是我复制代码时遗漏了一些对FF来说不重要,但对IE却是必需的代码呢?

    毕竟我只复制了一小段,而且CSS在各个浏览器中也确实有可能出现不兼容的情况。

    为保险起见,我点击"查看源文件",并将其中的代码全部复制到测试页面中,运行,问题依旧。

    这使我非常郁闷,为什么相同的代码,在别人那是正常的,在我这却有问题呢?

    继续尝试。

    这次我决定将他的整个网页保存下来。

    于是我点击了IE的"另存为",将他的网页保存到本地,运行,效果出来了!

    现在可以肯定是我前面的代码哪里错了。于是我再将保存在本地的网页打开,查看其中的代码,发现IE对上面的CSS代码进行了格式化:

    A.files INPUT {
         FILTER: alpha(opacity=0); MARGIN-LEFT: -350px; FONT-SIZE: 30px; CURSOR: pointer; opacity: 0
    }

     
    大家就不用自己比对了,我直接说结果:这两段代码是完全一样的,除了大小写和属性定义的顺序之外。

    我们知道CSS是不区分大小写的,而且通常来说,不相干的属性之间的顺序也是无关紧要的。但我还是抱着谨慎求证的态度决定亲自验证一下,我将之前的CSS用这个替换掉,然后用IE打开,然后……显示正常!

    但谁能告诉我,这TM到底是为什么吗?

    难道真的是大小写或者顺序的原因?不管你信不信,反正我是不信。

    然后我决定再改回原来的代码再试一次。

    a.files input {
         margin-left:-350px;
         font-size:30px;
         cursor:pointer;
         filter:alpha(opacity=0);
         opacity:0;
    }

     
    用IE打开——他TM又没问题了!相同的代码,改回去再改回来,结果居然是不一样的?我当时就在想我是不是被上帝当成愤怒的小鸟给玩儿了?要不然怎么会发生这么反人类反科学的事情!

    忽然,我发现最后这段代码与原来的代码只有一点不同,那就是注释。

    难道……是……注释?

    不知道为什么,可能是灵感突发,我忽然想到了编码这个问题。我在IE中查看了我的测试页面的编码:GB2312;我又查看了原网页的编码:UTF-8

    事实证明,果然是编码的问题。然而更多的问题来了:

    1. 为什么编码会影响到效果?

    2. 我查看了两个页面在FF下的编码,情况和IE是一样的(一个是UTF-8另一个是GB2312),为什么FF都可以正常显示呢?

    3. 我后来是将整个页面通过"查看源文件"的方式复制下来的,为什么会和原网页的默认编码不一样呢?

    经过一番思考和验证,我终于找到了第1和第3个问题的答案:

    1.为什么编码会影响到效果

    IE错误地解释了注释/*file设为透明,并覆盖整个触发面*/,因为这段字符是UTF-8编码的,最后的"面*/"三个字符的UTF-8编码为:0xE99DA2(面)、0x2A(*)、0x2F(/)

    UTF-8将汉字用3个字节来编码,对英文字符是1个字节。GB2312对汉字是2字节,对英文字符和UTF-8一样是1字节

     
    当IE试图用GB2312解释这段注释时,它错误地将0xA2(“面”字的最后一个字节)和0x2A(*)组合在一起,形成了GB2312字符:0xA22A,虽然最后的"/"正常解释,但"*"字符丢失导致了本该结束的注释没有结束。

    我试着将注释内容换成别的中文字符,如"中中",发现在IE下也没有问题了,看来这是一个由不恰当的中文注释恰好导致的一个偶然的错误(很拗口吧,我故意的)

    3. 为什么通过“查看源文件”扒下来的内容会和原网页的默认编码不一样

    我仔细查看了使用“另存为”保存的页面源代码,其中有这么一句:

    <META content="text/html; charset=utf-8" http-equiv=Content-Type>

     
    原来人家设置了页面的默认编码为UTF-8的,但我的测试页面中却没有,所以IE使用了错误的编码来解析,导致出错。但诡异的是,我在"查看源文件"时无论是IE还是FF都没有这一句。这就是为什么我将“查看源文件”中的所有内容都复制过来也还是不行的原因。

    至于第2点,我始终不太理解,为什么同样的情况IE不行但FF却是正常的?个人猜测是两个浏览器在实现上的差异导致的。如果你知道具体原因,希望能够不吝赐教。

    ------------------------------------

    下面是总结时间:

    1. 浏览器的"查看源文件"和真正的源文件是有差别的

    2. 注释有时也会对程序的运行产生影响

    在《Java解惑》一书中也提到过因为注释而产生问题的例子。书中的谜题15"令人晕头转向的Hello"和谜题16"行打印程序"两节,作者列举了两个因为注释而导致问题的例子:
    
    谜题15的例子:
    
        /**
         * Generated by the IBM IDL-to-Java compiler, version 1.0
         * from F:TestRootappsa1unitsincludePolicyHome.idl
         * Wednesday, June 17, 1998 6:44:40 o’clock AM GMT+00:00
         */
    
    如果你没看过Java解惑这本书,估计很难一眼看出问题在哪,只是一段普通的注释嘛。
    
    问题出在注释中的"units"这里,"u"在Java中用来对Unicode字符进行转义,后面必需紧跟着4位十六进制数字,即字符的Unicode编码。但这里,"units"显然违反了此约定。
    
    谜题16的例子:
    
        // Note: u000A is Unicode representation of linefeed (LF)
    
    这个例子的问题与我遇到的这个问题就更相似了。"u000A"是一个Unicode换行符,因此在编译时,这行注释将被编译器理解为:
    
        // Note:
    
         is Unicode representation of linefeed (LF)
    
    
    显然,这也是无法通过编译的。


    3. 最后,一些看似可有可无的细节也有可能会导致莫名其妙的问题。因此在平时写程序时要注意总结和遵守规范。不要嫌这些规范死板和繁琐,它们都是前人根据多年的经验总结下来的,通常能够让你远离错误。

    好了,今天就到此为止吧,一个看似简单的小问题,随便记录一下。

  • 相关阅读:
    UNIX环境高级编程——信号说明列表
    [Fiddler]如何让Fiddler可以抓取https的请求
    [Cookie] Read Cookie and Pass in headers
    [Training Video
    [Training Video
    [Training Video
    [Training Video
    [Training Video
    [Training Video
    [Training Video
  • 原文地址:https://www.cnblogs.com/antineutrino/p/3770207.html
Copyright © 2020-2023  润新知