退一步说, JavaScript处理Unicode时有些怪异. 这篇文章会说明JS在Unicode上令人痛苦的部分, 然后提供解决方案, 并说明在未来的ECMAScript6中是如何改善这些问题的.

 
Unicode基础知识
为了您能更好的理解Unicode在JavaScript里的问题, 先确保大家了解Unicode为何物.
最简单的我们可以把 Unicode 想像成一个数据库, 任何您能想到的符号都对应着一个数字(我们把这个数字叫做它的码位)和一个唯一的名字. 这样一来, 我们可以方便的引用一个符号, 而不必直接使用这个符号本身.
例如:
A U+0041 LATIN CAPITAL LETTER A
a U+0061 LATIN SMALL LETTER A
© U+00A9 COPYRIGHT SIGN
U+2603 SNOWMAN
U+1F4A9 PILE OF POO
 
码位通常用16进制数字表示, 用0补位, 至少4位数加上 U+ 前缀.
码们的范围是从U+0000至U+10FFFF. 可以表示110万个以上的符号.为了良好的组织如此庞大的数据, Unicode把这些码们分成了17个平面, 大约每个平面包含了6.5万个码位.
第一部分也是最重要的部分叫做基本多文种平面或BMP, 这部分包含了我们通常会用到的符号. 在英文文本文档中通常来说您只需要使用BMP就足够了.
BMP之外还剩下100万个可用码位..包含这100万个码位的平面叫做补充平面星际平面.
星际平面十分容易辨识: 当您需要使用大于4位的16进制数来表示码位时, 这个码位就是星际码位.
现在我们已经了解了Unicode基础知道, 下面来看看它是如何应用到JavaScript的字符串里的.
 
转义序列
您之前可能见过下面这些东西:
>> '\x41\x42\x43'
'ABC'
>> '\x61\x62\x63'
'abc'
这些叫做16进制转义序列. 它们包含2位16进制数字表示码位. 比如, '\x41' 表示 U+0041 LATIN CAPITAL LETTER A. 细心的读者可能发现了, 这些转义序列可以表示U+0000至U+00FF的码位.
 
还有一种常见的转义:
>> '\u0041\u0042\u0043'
'ABC'
>> 'I \u2661 JavaScript!'
'I ♡ JavaScript!'
这些叫做Unicode转义序列. 它们使用4位16进制数表示一个码位. 比如: '\u2661' 表示 U+2661 WHITE HEART SUIT. 这些转义序列表示的范围是U+0000至U+FFFF, 包含了全部的BMP.
 
那么对于其它平面呢? 比如星际平面? 我们需要4位以上的16进制数才能表示它们的码位... 如何来转义??
 
在 ECMAScript 6 里, 这个很简单, 因为添加了一种新的转义方式: Unicode码位转义.
例如:
>> '\u{41}\u{42}\u{43}'
'ABC' >> '\u{1F4A9}'
'' // U+1F4A9 PILE OF POO
(好吧.. 我的编辑器已经显示不了 PILE OF POO 了 - -!). 在大括号之前你可以使用最多6位16进制数, 可以表示出所有的Unicode码位.
为了向后兼容ECMAScript5和更早的环境, 一个不好的方案就是使用替代组合:
>> '\uD83D\uDCA9'

'' // U+1F4A9 PILE OF POO
由两者组成一个星际符号. 要注意的是这两个组成部分已经失去了它们本身的码位意义.
使用这种替代组合后, 所有的星际码位都可以被表示了.. 大家应该已经感觉到了, 单个码位可以表示的BMP与需要替代组合才能表示的星际符号混在一起, 令人困惑, 甚至会造成讨厌的后果.
在JavaScript里计算字符数
如果你想计算字符串的长度你会怎么做?
我首先想到的是用 length 属性.
>> 'A'.length // U+0041 LATIN CAPITAL LETTER A
1 >> 'A' == '\u0041'
true >> 'B'.length // U+0042 LATIN CAPITAL LETTER B
1 >> 'B' == '\u0042'
true
上面的例子里, length 属性确实表示了字符的数量. (这说得通, 因为如果我们使用转义序列来表示这个字符, 只需要一个转义就可以(\u0041 表示 A)).
来看一个不一样的例子:

>> '퐀'.length // U+1D400 MATHEMATICAL BOLD CAPITAL A
2
>> '퐀' == '\uD835\uDC00'
true
>> '퐁'.length // U+1D401 MATHEMATICAL BOLD CAPITAL B
2
>> '퐁' == '\uD835\uDC01'
true
>> ''.length // U+1F4A9 PILE OF POO
2
>> '' == '\uD83D\uDCA9'
true

在JavaScript内部, 使用上文提到的替代组合来表示星际字符, 并且暴露出组成替代组合的2个字符. 如果你使用ECMAScript 5兼容的转义序列来表示符号, 就需要2个转义字符来表示一个星际符号. 这令人困惑, 因为人们通常是以一个Unicode符号或字母的一个整体来考虑它们, 而不是把一个星际字符想成2部分.
(未完待续)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

#翻译# 深入JavaScript的Unicode难题(上)的更多相关文章

  1. 【探索】机器指令翻译成 JavaScript

    前言 前些时候研究脚本混淆时,打算先学一些「程序流程」相关的概念.为了不因太枯燥而放弃,决定想一个有趣的案例,可以边探索边学. 于是想了一个话题:尝试将机器指令 1:1 翻译 成 JavaScript ...

  2. 机器指令翻译成 JavaScript —— No.5 指令变化

    上一篇,我们通过内置解释器的方案,解决任意跳转的问题.同时,也提到另一个问题:如果指令发生变化,又该如何应对. 指令自改 如果指令加载到 RAM 中,那就和普通数据一样,也是可以随意修改的.然而,对应 ...

  3. [书籍翻译] 《JavaScript并发编程》第一章 JavaScript并发简介

    > 本文是我翻译<JavaScript Concurrency>书籍的第一章,该书主要以Promises.Generator.Web workers等技术来讲解JavaScript并 ...

  4. [书籍翻译] 《JavaScript并发编程》第五章 使用Web Workers

    本文是我翻译<JavaScript Concurrency>书籍的第五章 使用Web Workers,该书主要以Promises.Generator.Web workers等技术来讲解Ja ...

  5. [书籍翻译] 《JavaScript并发编程》第七章 抽取并发逻辑

    本文是我翻译<JavaScript Concurrency>书籍的第七章 抽取并发逻辑,该书主要以Promises.Generator.Web workers等技术来讲解JavaScrip ...

  6. [书籍翻译] 《JavaScript并发编程》第六章 实用的并发

    本文是我翻译<JavaScript Concurrency>书籍的第六章 实用的并发,该书主要以Promises.Generator.Web workers等技术来讲解JavaScript ...

  7. [书籍翻译] 《JavaScript并发编程》第四章 使用Generators实现惰性计算

    本文是我翻译<JavaScript Concurrency>书籍的第四章 使用Generators实现惰性计算,该书主要以Promises.Generator.Web workers等技术 ...

  8. [书籍翻译] 《JavaScript并发编程》第三章 使用Promises实现同步

    本文是我翻译<JavaScript Concurrency>书籍的第三章 使用Promises实现同步,该书主要以Promises.Generator.Web workers等技术来讲解J ...

  9. [书籍翻译] 《JavaScript并发编程》 第二章 JavaScript运行模型

    本文是我翻译<JavaScript Concurrency>书籍的第二章 JavaScript运行模型,该书主要以Promises.Generator.Web workers等技术来讲解J ...

随机推荐

  1. 使用cocoapods导入第三方后 报错_OBJC_CLASS_$_XXX

    我们手动导入第三方库的时候,感觉管理不是很方便,于是会选择使用Cocoapods管理.现在记录一下使用心得,当使用cocoapods导入afnetworking或者其他框架的时候,发现调用的时候总是报 ...

  2. 关于PHP的curl开启问题 (转)

    今天在做一个新浪登录功能,新浪提供的PHP SDK里需要用到curl_init()函数,在调试的时候报找不到curl_init()的方法. 经搜索得知需要开启curl的php扩展,那curl又是什么呢 ...

  3. Difference between Tomcat's extraResourcePaths and aliases to access an external directory--转

    Question: Simple question: In Tomcat7, what's the difference between using extraResourcePaths and al ...

  4. Android(java)学习笔记255:JNI之JNI概念

    1. JNI是什么? java native interface (java本机接口) 比如方法声明: public final native Class<?>  getClass(): ...

  5. Android(java)学习笔记258:JNI之hello.c(c代码功能实现)指针语法解析

    1. 接下来我们细讲分析一下前面一讲中,c功能实现的代码: (1)hello.c : #include <jni.h> char* getHello() { //////// return ...

  6. css实现鼠标移上去变大,旋转,转别人的额

    <!doctype html><html><head> <meta charset="utf-8"> <title>CS ...

  7. ASP.NET-FineUI开发实践-9(三)

    1. TextChanged事件前台触发回发后台,接上文,先给TextBox1加上事件,看看是怎么生成出来的, 注意AutoPostBack="true",找源代码,f4多出了个 ...

  8. C# KTV 系统 SQL数据库连接 C# 应用窗体

    ---恢复内容开始--- 五道口 北大青鸟校区 KTV项目 指导老师: 袁玉明  SQL数据库关系图 第一步: private void DoubleClicklvContry() { ]!=null ...

  9. maven第三章 maven使用入门

    3.1编写pom groupId 一个项目名称 artifactId 子项目(模块)名称 version 开发中的版本,稳定的版本 name 项目名称,方便信息交流 http://news.cnblo ...

  10. HTML5新增的属性和废除的属性

    HTML5中,在新增加和废除很多元素的同时,也增加和废除了很多属性. 新增的属性 1.表单相关的属性 对input(type=text).select.textarea与button指定autofoc ...