最近在看《JavaScript权威指南(第六版)》,里面有个例子,是说的

"a" < "b"     // => true

然后我就想了,那中文字符可以进行这样的比较吗,然后就在Chrome的控制台里面测试了一下

"大" < "小"     // => true
"小" < "大"     // => false

那它们是如何比较的?

书里面有这样一句话:

Unicode允许使用多种方法对同一个字符进行编码。比如,字符“é”可以使用Unicode字符u00E9表示,也可以使用普通的ASCII字符e跟随一个语调符u0301。在文本编辑器中,这两种编码的显示结果一模一样,但它们的二进制编码表示是不一样的,在计算机里也不相等。Unicode标准为所有字符定义了一个首选的编码格式,并给出了一个标准化的处理方式将文本转换为一种适合比较的标准格式,JavaScript会认为它正在解析的程序代码已经是这种标准格式,不会再对其标识符、字符串或正则表达式作标准化处理。

对这句话不是很理解,看的很晕。是说的在JavaScript解析之前,已经有程序把它的所有代码转变成了另一种格式的编码吗,而且还不是二进制的

后来偶然看到有encodeURICompent()这样个函数,一般是用来处理URI里面的数据,把一些特殊字符和中文等等进行十六进制编码,以便在不同平台上面数据都能很好使用

然后我就试了下

encodeURIComponent("大");        // =>%E5%A4%A7
encodeURIComponent("小");        // =>%E5%B0%8F

很明显,转化成十六进制之后,”小”的值是大于”大”的

我想,是不是在JavaScript解析之前,浏览器就根据Unicode标准用类似的方式把代码进行了编码,所以等到JavaScript解析的时候,比较”大”>”小”,实际上是类似于在比较”%E5%A4%A7″>”%E5%B0%8F”

不知道有人能跟我讲解一下这方面的知识不,感激不尽

今天工作上面需要对一个表单进行验证,需要判断中文。在网上看到了很多的方式

1. GBK (GB2312/GB18030)
x00-xff  GBK双字节编码范围
x20-x7f  ASCII
xa1-xff  中文
x80-xff  中文

2. UTF-8 (Unicode)
u4e00-u9fa5 (中文)
x3130-x318F (韩文
xAC00-xD7A3 (韩文)
u0800-u4e00 (日文)
ps: 韩文是大于[u9fa5]的字符

 

x是十六进制,u是Unicode编码,这种理解对吗

两者之间有什么区别和联系呢

 

2012年8月15日补充

JavaScript的字符串是使用Unicode编码的,每个字符占用两个字节。编码的方式是Unicode 16,具体是Little-Endian还是Big-Endian则要看操作系统了。所以在针对JavaScript的字符串使用正则时,针对中文使用u4e00-u9fa5

参考文章:http://demon.tw/programming/javascript-unicode-utf-8.html

关于Unicode 16的Little-Endian和Big-Endian,可以参看维基百科:https://zh.wikipedia.org/wiki/%E5%AD%97%E8%8A%82%E5%BA%8F

一直以来,但凡涉及到getElementById,getElementsByTagName,总是会习惯性的在前面加上document对象。就像昨天写的一个博客里面,有个关于清空指定id的后代节点中input type=”text”的内容的函数(传送门)。当我通过document.getElementById()获取指定的ID的对象之后,就开始很傻的一步步的遍历每个节点,看它是不是input type=“text”的;还看改节点有没有子节点,有的话,有几个,然后再考虑是否遍历查找。

代码如下:

 /**
  * [clearUserInput 根据元素的ID找到其子节点(包括子节点的子节点)
中的input元素并且type="text",将其value设为空]
  * @param  {[type]} id [DOM对象或者字符串表示元素的id值]
  * @return {[type]}    [description]
  */
 function clearUserInput(id){
     //参数校验
     if(id === undefined){consoloe.log("参数必须");return 1;}//判断参数是否存在
     id = ((typeof id) === "object")?id:document.getElementById(id);//获取对象
     if(id === null){consoloe.log("未知对象"); return 2;}//typeof null === "object"

     var childrens = id.childNodes,len=childrens.length; i=0;
     for(i;i<len;i++){
         if(childrens[i] === undefined){return;}//到达边界
         if(childrens[i].nodeType === 3){continue;}
         if(childrens[i].childNodes.length !== 0){
             arguments.callee(childrens[i]);//循环遍历        
         }
         if(childrens[i].nodeName === "INPUT" && childrens[i].type === "text"){
             childrens[i].value = "";//内容设为空
         }
     }
 }

 

最后,功能上面实现了,可是每次点击清除的时候,整个浏览器和卡机了差不多…..遍历的计算次数太多了

后来我偶然一下突然想了,既然document对象有getElementsByTagName()之类的方法,那其他的节点和document对象理论上应该是没差的,那它们是不是也应该有这些方法?

我就测试了下,果然一个div对象是有getElementsByTagName()的方法,可是没有getElementById()的方法

元素类型 节点类型
元素 1
属性 2
文本 3
注释 8
文档 9

document.nodeType == 9

一般的HTML标签,如div,p等等,他们的DOM对象的nodeType == 1

就我所知的,nodeType == 1的DOM对象仅有getElementsByTagName()的方法

之后我根据这个修改了一下代码

 /**
  * [clearUserInput 根据元素的ID找到其子节点(包括子节点的子节点)中的input元素并且type="text",将其value设为空]
  * @param  {[type]} id [DOM对象或者字符串表示元素的id值]
  * @return {[type]}    [description]
  */
 function clearUserInput(id){
     //参数校验

     //判断参数是否存在
     if(id === undefined){return 1;}
     //获取对象
     id = ((typeof id) === "object")?id:document.getElementById(id);
     //typeof null === "object"
     if(id === null){return 2;}
     //找到后代节点中的所有input标签
     var inputs = id.getElementsByTagName("input"),
     len=inputs.length, i=0;
     for(i;i<len;i++){
         //到达边界
         if(inputs[i] === undefined){return 3;}
         if(inputs[i].nodeName === "INPUT" && inputs[i].type === "text"){
             inputs[i].value = "";//内容设为空
         }
     }
 }

效率果然显著提升

一直以来都有这样一个属于程序员的意淫:开通一个博客,设计一个很炫的界面,写很多技术方面的文章,然后会有人说谢谢分享、会有人跟你讨论文章里面的一个又一个细节。

今天,这个想法踏出一小步了!

希望自己能够坚持维护这个博客,让它伴随着我一同成长,XD