zoukankan      html  css  js  c++  java
  • #翻译# 深入JavaScript的Unicode难题(上)

    退一步说, 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的字符串里的.
     
    转义序列
    您之前可能见过下面这些东西:
    >> 'x41x42x43'
    'ABC'
    >> 'x61x62x63'
    'abc'
    
    这些叫做16进制转义序列. 它们包含2位16进制数字表示码位. 比如, 'x41' 表示 U+0041 LATIN CAPITAL LETTER A. 细心的读者可能发现了, 这些转义序列可以表示U+0000至U+00FF的码位.
     
    还有一种常见的转义:
    >> 'u0041u0042u0043'
    '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和更早的环境, 一个不好的方案就是使用替代组合:
    >> 'uD83DuDCA9'
    
    '' // 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
    >> '퐀' == 'uD835uDC00'
    true
    >> '퐁'.length // U+1D401 MATHEMATICAL BOLD CAPITAL B
    2
    >> '퐁' == 'uD835uDC01'
    true
    >> ''.length // U+1F4A9 PILE OF POO
    2
    >> '' == 'uD83DuDCA9'
    true
    
    
    
    在JavaScript内部, 使用上文提到的替代组合来表示星际字符, 并且暴露出组成替代组合的2个字符. 如果你使用ECMAScript 5兼容的转义序列来表示符号, 就需要2个转义字符来表示一个星际符号. 这令人困惑, 因为人们通常是以一个Unicode符号或字母的一个整体来考虑它们, 而不是把一个星际字符想成2部分.
    
    (未完待续)
    
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
  • 相关阅读:
    生活感悟
    shell语法
    mycat
    阐述 如何高效理解学习
    部署ETCD集群
    文件修改
    文件处理
    a's
    shell中备份web站点及数据库
    openssh版本升级修复漏洞
  • 原文地址:https://www.cnblogs.com/patrick-holynova/p/3751574.html
Copyright © 2011-2022 走看看