字符集
JS程序是用Unicode字符集编写的.Unicode是ASCII和Latin-l的超集,并持之地球上几乎所有再用的语言.ECMAScript 3要求JS的实现必须支持Unicode2.1以及后续版本,ECMAScript5则要求支持Uniocde 3及以后版本.
区分大小写
JS是区分大小写的语言.也就是说,关键字,变量,函数名和所有的标识符都必须采取一致的大小写形式.比如,关键字”while”必须写成”while”,而不能写成”WHILE”或者”While”.以上这三种while是三种不同的变量名.
但需要注意的是,HTML并不区分大小写(尽管XHTML区分大小写).由于他和客户端JS 练习紧密,因此这点区别很容易混淆.许多客户端JS对象和属性与它们所表示的HTML标签和属性同名.在HTML中,这些标签和属性可以使用大写也可以是小写,而在JS中则必须是由小写.例如:在HTML中设置事件处理程序时,onclick属性可以写成OnClick,但在JS代码或者在XHTML文档)种,必须使用小写的onclick.
空格,换行符和格式控制符
JS会忽略程序中的标识之间的空格.多数情况下,JS同样会忽略换行符.由于可以在代码中随意使用空格和换行,因此可以采用整齐,一致的缩进来形成统一的编码风格,从而提高代码的可读性.
Unicode转义序列
在有些计算机硬件和软件里,无法显示或输入Unicode字符全集.为了支持那些使用老旧技术的程序员,JS定义了一种特殊序列,使用6个ASCII字符来代表任意16位Uniocde内码.这些Uniocde转义序列均以\u为前缀,其后跟随4个十六进制数(使用数字以及大写或小写的字母A~F表示).这种Unicode转义写法可以用JS字符串直接量,正则表达式直接量和标识符中(关键字除外).
标准化
Unicode允许使用多种方法对同一个字符进行编码.Unicode标准为所有字符定义了一个首选的编码格式,并给出了一个标准化的处理方式将文本转换为一种适合比较的标准格式,JS会认为它正在解析的程序代码已经是这种标准格式,不会在对其标识符,字符串或正则表达式做标准化处理.
JS的注释
JS支持两种注释方式:
1.//
解释,//注释一行,//后面的内容为注释内容
2./**/
解释:/**/注释一片,/**/里面的内容为注释内容.
直接量
什么叫直接量?所谓的直接量,就是在程序中直接使用的数据值,不用定义,是不是很吊?
下面列出一些直接量:
12 //数字
1.2 //小数
“hello,world ” //字符串文本
‘hi’ //另一个字符串,虽然是单引号,但也是字符串
true //布尔值
/js/gi //正则表达式直接量(用来匹配的的)
数组和对象也可以写成直接量:
{x:1,y:2} //对象
[1,2,3,4,5] //数组
标识符和保留字
标识符就是一个名字,在JS中,标识符用来给变量和函数起名字,或者用作JS代码中某些循环语句中的跳转位置的标记(这个以后碰到了再说).
JS标识符的也不能随便瞎起,就像一个人的名字不能瞎起一样,比如一个中国人,你让它叫安倍晋二,那绝对是不行的,JS标识符必须以字母,下划线(_)或美元符($)开始.后续的字符可以是字母,数字,下划线或美元符(数字不能开头,这是为了区分标识符和数字).下面列出几个合法的标志符:
i
my_variable_name
vi3
_dumy
$str
因为将来我们的代码可能会被微软谁的采用,所以我们通常只使用ASCII字母和数字来书写标志符.然而需要注意注意的是,JS允许标志符中出现Unicode字符全集中的字母和数字.
常说Unicode字符集,那么Unicode到底是个什么东西?
ASCII码
我们知道,在计算机的内部,所有的信息最终都表示为一个二进制的字符串.每一个二进制位(bit)有0和1两种状态,因此八个二进制位就可以组成256种状态,这被称为一个字节(8位).也就是说,一个字节一共可以用来表示256中不同的状态,每一个状态对应一个符号,就是256个符号,从00000000到11111111.
上个世纪60年代,美国指定了一套字符编码(万恶的美帝),对英语与字符与二进制位之间的关系,做出了统一的规定.这杯称为ASCII码,此码一直沿用至今.
ASCII码一共规定了额28个字符的编码,比如空格”SPACE”是32(00100000),大写字母A是65(二进制01000001).这129个符号(包括32个不能打印出来的控制符号,例如回车,删除,tab键),只占用了一个字节的后面7位,嘴欠的一位统一规定为0.
非ASCII编码
英语用128个符号编码就够了,一共才26个英文字符,键盘一共才几个键啊,但是其他语言就不行了,最先发现ASCII不足的是欧美,不是欧美,是欧洲(最近日韩欧美接触的有点多).这些国家的语言比较复杂,128种符号无法满足他们的需要,因为他们施工的”汉字”不止128个,不像老美那样26个英文字母搞定.这样一来,这些欧洲国家使用的编码体系,可以表示最多256个符号.
但是,问题由来了,不同的国家有不同的字母,因此,哪怕他们都是用256个符号的编码方式,代表的字母却不一样.比如130在法语中可能代表(fuck),在西班牙语中可能代表(love).在意大利又不同.不管咋样,所有这些编码方式中,0-127表示的符号是相同的(因为老美规定好了),不一样的只是128-255的这一段(因为没人规定,所以大家都自己弄自己的).
看到ASCII的时候,中国笑了,我TM光汉字就有10W+,还有56个少数民族的语言,各地的方言我就不说了,你TM一个字节最多表示256中符号,逗我呢,256个字还不够我写一遍小学生作文了(最低要求400字),逗我呢?所以只能想办法,使用多个字节表达一个符号.比如,简体中文常见的编码方式GB2312,使用两个字节表示一个汉字,所以理论上最多可以表示256*256=65536个符号.
Unicode
正如上面说的,世界上存在着多种编码方式,同一个二进制数字可能被解释成不同的符号.因此,要想打开一个文本文件,就不洗直到他的编码方式,否则用错误的编码方式打开,就会出现乱码.为什么调子邮件常常出现乱码?就是因为,我用英语给你发的邮件,你用意大利语给我读的.
可以想象,如果有一种编码,将世界上所有的符号都纳入其中.每一个符号都给与一个独一无二的编码,那么乱码问题就睡消失比如,规定JB代码的含义就是帅哥,我不管走到哪里,我说JB,大家肯定偶知道这是帅哥的意思.就相当于国际语言.
在字符编码表中,这种国际语言叫做Unicode,这是一种所有符号的编码.
Unicode当然是一个很大的集合,现在的规模可以容纳100多万个符号(不知道中国的方言有没有在里面..),每个符号的编码都不一样,比如U+1234表示阿拉伯字母Ain,U+1234只能表示这个阿拉伯字母,不能表示其他的字母了,他已经让别人实名认证了.
Unicode的问题
需要注意的是,Unicode只是一个符号集,它值规定了符号的二进制代码,却没有规定这个二进制代码应该如何存储.
比如,汉字"严"的unicode是十六进制数4E25,转换成二进制数足足有15位(100111000100101),也就是说这个符号的表示至少需要2个字节。表示其他更大的符号,可能需要3个字节或者4个字节,甚至更多。
这里就有两个严重的问题,第一个问题是,如何才能区别Unicode和ASCII?计算机怎么知道三个字节表示一个符号,而不是分别表示三个符号呢?第二个问题是,我们已经知道,英文字母只用一个字节表示就够了,如果Unicode统一规定,每个符号用三个或四个字节表示,那么每个英文字母前都必然有二到三个字节是0,这对于存储来说是极大的浪费,文本文件的大小会因此大出二三倍,这是无法接受的。
它们造成的结果是:1)出现了Unicode的多种存储方式,也就是说有许多种不同的二进制格式,可以用来表示Unicode。2)Unicode在很长一段时间内无法推广,直到互联网的出现。
UTF-8
互联网的普及,强烈要求出现一种同一的编码方式,不是有了Unicode了吗?怎么还强烈要求啊?!!往下砍,UTF-8是在互联网上使用最广发的一种Unicode的实现方式.其他实现方式还包括UTF-16(字符用两个或四个字街表示)和UTF-32(字符用4个字节表示),-16和-32 基本不用.这里的关系是:UTF-8是Unicode的实现方式之一.-8和Unicode虽然都是使用多个字节表示一个符号,但是GB(不是JB)类的汉字编码与的Unicode和UTF-8是没有半毛钱关系的.
UTF-8最大的一个特定,就是它是一种变长的编码方式.他可以使用1-4字节表示一个符号;根据不同的符号而变化字节长度.
UTF-8的编码规则简单,只有两条:
(1)对于单字节的符号,字节的第一位设为0,后面的7位为这个符号的Unicode码.因此对于英文字母,UTF-8编码和ASCII吗是相同的.
(2)对于n字节的符号(n>1),第一个字节的前n位都设为1,第n+1位设为0,后面字节的前两位一律设为10.剩下的没有提及的二进制位,全部为这个符号的unicode码.
下标总结了编码规则,字母x表示可用编码的位
Unicode符号范围 | UTF-8编码方式
(十六进制) | (二进制)
--------------------+---------------------------------------------
0000 0000-0000 007F | 0xxxxxxx
0000 0080-0000 07FF | 110xxxxx 10xxxxxx
0000 0800-0000 FFFF | 1110xxxx 10xxxxxx 10xxxxxx
0001 0000-0010 FFFF | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
根据上表,解读UTF-8编码非常简单.如果每一个字节的第一位是0,则这个字节单独就是一个字符;如果第一位是1,则连续有多少个1,就表示当前字符占用多少个字节.
已知"严"的unicode是4E25(100111000100101),根据上表,可以发现4E25处在第三行的范围内(0000 0800-0000 FFFF),因此"严"的UTF-8编码需要三个字节,即格式是"1110xxxx 10xxxxxx 10xxxxxx"。然后,从"严"的最后一个二进制位开始,依次从后向前填入格式中的x,多出的位补0。这样就得到了,"严"的UTF-8编码是"11100100 10111000 10100101",转换成十六进制就是E4B8A5。
Unicode与UTF-8之间的转换
通过上面的案例,可以看到”严”的Unicode码是4E25,UTF-8编码是E4B8A5,两者是不一样的。它们之间的转换可以通过程序实现。
在Windows平台下,有一个最简单的转化方法,就是使用内置的记事本小程序Notepad.exe。打开文件后,点击"文件"菜单中的"另存为"命令,会跳出一个对话框,在最底部有一个"编码"的下拉条。
里面有四个选项:ANSI,Unicode,Unicode big endian和UTF-8
(1)ANSI是默认的编码方式.对于英文文件是ASCII编码,对于简体中文是GB2312编码(只针对window简体中文本,如果是繁体中文本会采用big5码)
(2)Unicode编码指的是UCS-2编码方式,即直接用两个字节存入字符的Unicode码.这个选项用的little endian格式.
(3)Unicode big endian 编码与上一个选项相对应.后面介绍little endian和big endian的含义.
(4)UTF-8编码
选择好编码方式后,单击保存按钮,文件的编码方式就立刻转换好了.
little endian和big endian
不好解释,以案例为主,以汉字"严"为例,Unicode码是4E25,需要用两个字节存储,一个字节是4E,另一个字节是25。存储的时候,4E在前,25在后,就是Big endian方式;25在前,4E在后,就是Little endian方式。
这两个古怪的名称来自英国作家斯威夫特的《格列佛游记》。在该书中,小人国里爆发了内战,战争起因是人们争论,吃鸡蛋时究竟是从大头(Big-Endian)敲开还是从小头(Little-Endian)敲开。为了这件事情,前后爆发了六次战争,一个皇帝送了命,另一个皇帝丢了王位。
因此,第一个字节在前,就是"大头方式"(Big endian),第二个字节在前就是"小头方式"(Little endian)
那么很自然的,就会出现一个问题:计算机怎么知道某一个文件到底采用哪一种方式编码?
Unicode规范中定义,每一个文件的最前面分别加入一个表示编码顺序的字符,这个字符的名字叫做"零宽度非换行空格"(ZERO WIDTH NO-BREAK SPACE),用FEFF表示。这正好是两个字节,而且FF比FE大1。
如果一个文本文件的头两个字节是FE FF,就表示该文件采用大头方式;如果头两个字节是FF FE,就表示该文件采用小头方式。
实例
下面,举一个实例。
打开"记事本"程序Notepad.exe,新建一个文本文件,内容就是一个"严"字,依次采用ANSI,Unicode,Unicode big endian 和 UTF-8编码方式保存。
然后,用文本编辑软件UltraEdit中的"十六进制功能",观察该文件的内部编码方式。
1)ANSI:文件的编码就是两个字节"D1 CF",这正是"严"的GB2312编码,这也暗示GB2312是采用大头方式存储的。
2)Unicode:编码是四个字节"FF FE 25 4E",其中"FF FE"表明是小头方式存储,真正的编码是4E25。
3)Unicode big endian:编码是四个字节"FE FF 4E 25",其中"FE FF"表明是大头方式存储。
4)UTF-8:编码是六个字节"EF BB BF E4 B8 A5",前三个字节"EF BB BF"表示这是UTF-8编码,后三个"E4B8A5"就是"严"的具体编码,它的存储顺序与编码顺序是一致的。
扩展内容介绍完毕,回归正题
JS中把一些标识符拿出来作为自己的关键字.因为不能再使用这些关键字作为自己的标识符了,以下是关键字:
break delegate function return typeof case do if
seitch var catch else in this void contine ` false instanceof throw while debugger finally new true with default
for null try
以上这些关键字都在JS中有特殊含义,接下来这些没有特殊含义,作为保留关键字,这些关键字现在没有使用,但在将来版本中可能会用到.ECMAScript 5保留着这些关键字:
class const enum export import super
此外,一下这些关键字虽然是合法的,但是尽量不要使用,浙西在严格模式下是保留字:
implements let private public yield interface
package protected static
严格模式同样对下面的标志符的使用做了严格限制,他们并不完全是保留字,但不能用作变量名,函数名或参数名:
arguments eval
ECMAScript 3 将java的所有关键字都列为自己的保留字,尽管这些保留字在ECMAScript5中放宽了限制,但如果你希望代码能在基于ECMAScript3实现的解释器上运行的话,应当避免使用这些关键字作为标识符:
abstract double goto native static boolean enum
implements package super byte export
import private synchronized char extends int protected throws class final interface public
transient const float long short volatile
JS预定义了很多全局变量和函数,应当避免把他们的名字用作变量名和函数名:
arguments encodeURI Infinity Number RegExp
Array encodeURIComponent isFinite Object
String Boolean Error IsNaN ParseFloat SyntaxError
Date eval JSON ParseInt TypeError decodeURI
EvalError Math RangeError undefined decodeURIComponent Function NaN ReferenceError URIError
JS的具体实现可能定义独特的全局变量和函数,每一种特定的JS运行环境(客户端,服务端)都有自己的一个全局属性列表,这一点是需要牢记的.
版权声明:本文为博主原创文章,未经博主允许不得转载。