Emoji 那些事兒


如今 emoji 已經(jīng)成為文字交流的重要基礎(chǔ)。離開這些精巧的符號腹尖,只怕很多對話早就因?qū)擂魏驼`解而草草收場了。還記得當年短信風(fēng)行時的那些事嗎伐脖?

沒有笑臉表情的文字聊天過程中桐臊,常常會得到“你不是在開玩笑吧?”這樣的回復(fù)晓殊,以免將一些無聊的笑話信以為真断凶。后來并沒有花多久的時間,大家都明白了巫俺,單純靠文字來理解那些幽默與調(diào)戲并不那么容易(但不管怎么說认烁,這種套路確實應(yīng)該少一些)。世界上首個 emoji 誕生之后不久介汹,emoji 很快成為文字交流中不可或缺的要素却嗡。

日用之而不覺,我從未思考過 emoji 在技術(shù)層面上是如何工作的嘹承。但無論如何窗价,它們肯定和 Unicode 有關(guān)系,盡管我確實不了解實際機制叹卷。老實說撼港,我倒也沒怎么在意……

讀了 Wes Bos 的一條推文之后坪它,我的想法被徹底改變。Wes Bos 在這條推文中分享了一些 JavaScript 字符串操作帝牡,其中也包括表示家庭的 family emoji往毡。

[...'????????']?? // ["??", "?", "??", "?", "??"]

'????????'.length // 8

OK, 對字符串使用展開運算操作倒沒什么稀奇的,可是一個符號拆分出了三個符號外加兩個空字符靶溜,我頗有些疑惑开瞭。接著看到該符號的 length(長度) 竟然是 8,愈加困惑罩息,展開數(shù)組中明明就只有五項啊嗤详。

當即測試這段代碼,絲毫不爽瓷炮,果然如 Wes 所述断楷。什么鬼?不深入了解 Unicode崭别、JavaScript 和 emoji,就難解我心頭之惑恐锣。


Unicode 簡介

JavaScript 為什么會如此處理 emoji 呢茅主?欲要理解個中原理,還需深入去看 Unicode 本身土榴。

Unicode 是國際計算機工業(yè)標準诀姚。它是一個字母(或字符、符號)對應(yīng)一個數(shù)值的映射集玷禽。如果沒有 Unicode赫段,像那些含有像德文字母 ?、?矢赁、? 這樣的特殊字符的文檔糯笙,就無法在其他不使用這類字符的系統(tǒng)上共享。感謝 Unicode 的跨平臺撩银、跨系統(tǒng)編碼给涕。

Unicode 中共有 1,114,112 個不同的碼點(code point),它們通常使用 U+ 加上一個十六進制數(shù)字表示额获。Unicode 碼點取值范圍是 U+0000 到 U+10FFFF够庙。

這些碼點總數(shù)超過十億,它們被分為 17 個“平面”(plane)抄邀。每個平面包含六萬五千多個碼點耘眨。其中,最重要的平面是“多語言基本平面”(Basic Multilingual Plane境肾,BMP)剔难,范圍是 U+0000 至 U+FFFF胆屿。

BMP 基本平面幾乎包含了所有現(xiàn)代語言中使用到的字符,以及很多其他符號钥飞。其余 16 個平面稱作“補充平面”(Supplementary Planes)莺掠,其中包含一些不同的案例,比如——聰明如你读宙,可能已經(jīng)猜到了——大多數(shù) emoji 符號的定義彻秆。


emoji 是如何定義的

我們今天所知的 emoji 至少由一個 Unicode 碼點所定義〗嵴ⅲ可以看下 Full Emoji Data list唇兑,其中列出了所有定義的 emoji。你可能會問桦锄,Unicode 目前到底定義了多少不同的 emoji 呢扎附?答案是“視情況而定”,這可是計算機科學(xué)中常見的答案结耀。要回答這個問題留夜,首先需要理解 Unicode。

如前面所述图甜,emoji 至少由一個碼點定義碍粥。這也就意味著,還有一些 emoji 是由幾種不同的 emoji 和碼點組合而成的黑毅。這些組合稱作序列(sequence)嚼摩。有了序列,就可以做一些別的事矿瘦,比方說枕面,修飾那些中性 emoji (通常用黃色皮膚展示),讓它們符合你的風(fēng)格缚去。


修飾序列

猶記得當初在聊天中發(fā)現(xiàn)可以按自己的膚色修飾“點贊”表情的時候潮秘,我感受到了一種包容,這個表情與我之間的聯(lián)系似乎變得更加緊密了易结。

Unicode 中有五種修飾符唇跨,用于修飾與人相關(guān)的中性 emoji。不同的修飾符會產(chǎn)生不同膚色效果衬衬。修飾符基于 Fitzpatrick 量表 設(shè)定买猖,其編碼范圍為U+1F3FB~U+1F3FF。

下面是使用修飾符修改 emoji 膚色的示例:

// U+1F467 + U+1F3FD

?? + ??

> ????

在那些支持修飾序列的操作系統(tǒng)中滋尉,為碼點值為 U+1F467 的小女孩 emoji 添加修飾符之后玉控,就能得一個膚色發(fā)生變化的小女孩表情。


零寬連接序列

與人相關(guān)的狮惜,可不止膚色這一種高诺。再看看前面提到的家庭 emoji碌识,顯然并非所有家庭都是由爸爸、媽媽虱而、兒子三者組成的筏餐。

Unicode 中包括一個中性的表示家庭的碼點(U+1F46A– ???),但這并非家庭真實寫照牡拇。不過魁瞪,還可以使用“零寬連接符”序列(Zero-Width-Joiner sequence)創(chuàng)建一些不同的家庭符號。

先來談?wù)劰ぷ髟恚篣nicode 中有一個稱為零寬連接符(U+200D)的碼點惠呼。它就像膠水一樣导俘,將兩個碼點粘在一起以單個符號的形式展現(xiàn)。

想想要組成一個家庭的話剔蹋,需要將哪些符號連在一起呢旅薄?很簡單,兩個大人泣崩,一個孩子少梁。使用零寬連接符很容易就能拼出各種各樣的家庭符號。

// 中性家庭

// U+1F46A

> ??

// 零寬連接序列: 家庭 (男人, 女人, 男孩)

// U+1F468 + U+200D + U+1F469 + U+200D + U+1F466

// ??? + U+200D + ??? + U+200D + ??

> ?????????

// 零寬連接序列: 家庭 (女人, 女人, 女孩)

// U+1F469 + U+200D + U+1F469 + U+200D + U+1F467

// ??? + U+200D + ??? U+200D + ??

> ?????????

// 零寬連接序列: 家庭 (女人, 女人, 女孩, 女孩)

// U+1F469 + U+200D + U+1F469 + U+200D + U+1F467 + U+200D + U+1F467

// ??? + U+200D + ??? + U+200D + ??? + U+200D + ??

> ????????????

可以查看全部的零寬連接序列矫付,其中的類型更加多種多樣凯沪,比如,帶著兩個女孩的父親技即。不幸的是,在本文寫作的時候樟遣,這些序列的支持度并不是很好而叼。好在零寬連接序列還能優(yōu)雅降級,單個碼點分別獨立顯示豹悬。這有助于保持特殊組合符號的語義葵陵。

// 零寬連接序列: 家庭 (男人, 女孩, 女孩)

// U+1F468 + U+200D + U+1F467 + U+200D + U+1F467

// ??? + U+200D + ?? + U+200D + ??

> ???????????-> 尚不支持的情況下以這種形式顯示

還有很棒的一點是,上面這些原則并不是僅僅針對家庭 emoji 的瞻佛。來看看著名的 David Bowie emoji(該 emoji 的真名應(yīng)該是“男歌手”)脱篙。這個表情實際上也是一個零寬連接序列,由一個男士(U+1F468)伤柄、一個零寬連接符和一個耳機(U+1F3A4)組成绊困。

可能你已經(jīng)猜到了,將男人(U+1F468)替換成女人(U+1F469)适刀,結(jié)果就是一個女歌手(女版 David Bowie)秤朗。若再引入可以修改膚色的修飾符,還可能出現(xiàn)一個黑人女歌手笔喉。棒棒噠取视!

// 零寬連接序列: 女歌手

// U+1F469 + U+1F3FF + U+200D + U+1F3A4

// ?? + ?? + U+200D + ??

> ?????? -> 尚不支持的情況下以這種形式顯示

然而硝皂,依然不幸,目前這種序列的支持程度也并不是很好作谭。


emoji 數(shù)量

回答 emoji 到底有多少種稽物,得看怎么算了。是可用于展示 emoji 的不同碼點的數(shù)量嗎折欠?需要計算可以展示的各種不同的 emoji 變體嗎贝或?

如果計算可展示的不同 emoji(包括所有序列、變體)怨酝,總數(shù)是 2198傀缩。如果你對計算感興趣,可以看下 unicode.org 上的完整章節(jié)农猬。

除了“如何計算”這個問題之外赡艰,還有一個現(xiàn)實問題:新的 emoji 和 Unicode 字符在不斷加入規(guī)范,想要記錄準確的總數(shù)還是挺困難的斤葱。


JavaScript 字符串與 16 位代碼單元

JavaScript 字符串的格式是 UTF-16慷垮,使用一個 16 位的代碼單元表示最常見的字符。掐指一算揍堕,這意味著一個代碼單元能放下六萬五千多個碼點(譯者注:2^16=65536)料身,幾乎和 BMP 一一對應(yīng)。下面使用 BMP 中的一些符號試試看

'?'.length??// 1 -> U+FF82

'?'.length // 1 -> U+26F7

'?'.length // 1 -> U+9731

不出所料衩茸,這些字符的 length 值正好是 1芹血。可是楞慈,如果要用到的字符不在 BMP 范圍內(nèi)呢幔烛?


代理對

還可以將兩個 BMP 碼點結(jié)合在一起,形成一個新的碼點囊蓝,這就是代理對(surrogate pair)饿悬。

U+D800 到 U+DBFF 之間的保留碼點用于所謂的高級代理(又作 leading surrogates,主代理)聚霜,U+DC00 到 U+DFFF 之間的保留碼點則用于低級代理(又作 trailing surrogates狡恬,尾代理)。

這兩類碼點總是同時成對出現(xiàn)蝎宇,高級代理后面跟著低級代理弟劲。然后通過特定算法對超出范圍的碼點進行解碼。

一起來看下面的例子:

'??'.length??????????// 2

'??'.charCodeAt(0)?? // 55357??-> U+D83D // 返回主代理的碼點

'??'.charCodeAt(1)?? // 56424??-> U+DC68 // (譯者注:這個是尾代理碼點)

'??'.codePointAt(0)??// 128104 -> U+1F468 // 返回組合在一起的代理的碼點

'??'.codePointAt(1)??// 56424??-> U+DC68

中性的男性 emoji 的碼點是 U+1F468姥芥,在 JavaScript 中無法通過單個代碼單元來表示函卒。這就是為何需要使用代理對的原因,通過兩個單獨的代碼單元組成這個表情。

分析 JavaScript 中的代碼單元报嵌,有兩種可能有用的方法虱咧。一個是 charCodeAt,遇上代理對的時候锚国,該方法會分別返回每個代理的碼點腕巡。另一個方法是 codePointAt,遇上主代理時會返回代理對組合的碼點血筑,遇上尾代理時則返回尾代理的碼點绘沉。

看起來有點恐怖?深有同感豺总。強烈建議仔細 MDN 上的相關(guān)文章车伞。

再從數(shù)學(xué)方面深入看一下這個代表男性的 emoji。通過 charCodeAt 方法喻喳,我們可以檢索到組成代理對的獨立代碼單元另玖。

我們得到的第一個值是 55357,也就是十六進制的 D83D表伦,這個是高級代理谦去。得到的第二個值是 56424,即十六進制的 DC68蹦哼,這是低級代理鳄哭。這兩個典型的代理對經(jīng)過運算后便得到了 128104,映射到 emoji 就是男性符號纲熏。

// 十六進制

0x1F468 = (0xD83D - 0xD800) * 0x400 + 0xDC68 - 0xDC00 + 0x10000

// 十進制

128104 = (55357 - 55296) * 1024 + 56424 - 56320 + 65536

JavaScript 中的 length 屬性與碼點數(shù)量

學(xué)習(xí)了碼點的相關(guān)知識妆丘,現(xiàn)在可以理解這讓人困惑的 length 屬性了。它會返回的是碼點的數(shù)量局劲,而非一開始所認為的肉眼所見符號的數(shù)量勺拣。在處理 JavaScript 字符串的時候,這讓尋找 bug 變得相當麻煩容握。所以處理 BMP 平面之外的符號時千萬要當心宣脉。


小結(jié)

再回到 Wes 最初的例子车柠。

// 零寬連接序列: family (man, woman, boy)

// U+1F468 + U+200D + U+1F469 + U+200D + U+1F466

[...'????????']?? // ["??", "?", "??", "?", "??"]

'????????'.length // 8


// neutral family

// U+1F46A

[...'??']?? // ['??']

'??'.length // 2

我們在這里看到的家庭 emoji 由一個男性剔氏、一個女性、一個男孩組成竹祷。展開運算符會檢查所有碼點谈跛。我們所看到的空字符并非真正的空字符,而是零寬連接符塑陵。讀取該 emoji 的 length 屬性會得到 8感憾,其中每個 emoji 的 length 為 2,每個零寬連接符的 length 為 1令花,合起來正好是 8阻桅。

我真心享受深挖 Unicode 的過程凉倚。如果你同樣對這個話題感興趣,必須向你推薦 @fakeunicode 這個 Twitter 賬號嫂沉。你知道嗎稽寒,甚至還有關(guān)于 emoji 的 podcast 和會議 呢。我會保持關(guān)注的趟章,了解這些每天都在使用的小符號真是有趣極了杏糙,你可能也會感興趣的。

更多文章

一個emoji引發(fā)的思考


關(guān)注公眾號【grain先森】蚓土,回復(fù)關(guān)鍵詞 【18福利】宏侍,獲取為你準備的年終福利,更多關(guān)鍵詞玩法期待你的探索~

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末蜀漆,一起剝皮案震驚了整個濱河市谅河,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌嗜愈,老刑警劉巖旧蛾,帶你破解...
    沈念sama閱讀 219,270評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異蠕嫁,居然都是意外死亡锨天,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,489評論 3 395
  • 文/潘曉璐 我一進店門剃毒,熙熙樓的掌柜王于貴愁眉苦臉地迎上來病袄,“玉大人,你說我怎么就攤上這事赘阀∫娌” “怎么了?”我有些...
    開封第一講書人閱讀 165,630評論 0 356
  • 文/不壞的土叔 我叫張陵基公,是天一觀的道長幅慌。 經(jīng)常有香客問我,道長轰豆,這世上最難降的妖魔是什么龟再? 我笑而不...
    開封第一講書人閱讀 58,906評論 1 295
  • 正文 為了忘掉前任盟戏,我火速辦了婚禮麻裳,結(jié)果婚禮上洋访,老公的妹妹穿的比我還像新娘。我一直安慰自己斑司,他們只是感情好渗饮,可當我...
    茶點故事閱讀 67,928評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般互站。 火紅的嫁衣襯著肌膚如雪私蕾。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,718評論 1 305
  • 那天胡桃,我揣著相機與錄音是目,去河邊找鬼。 笑死标捺,一個胖子當著我的面吹牛懊纳,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播亡容,決...
    沈念sama閱讀 40,442評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼嗤疯,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了闺兢?” 一聲冷哼從身側(cè)響起茂缚,我...
    開封第一講書人閱讀 39,345評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎屋谭,沒想到半個月后脚囊,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,802評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡桐磁,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,984評論 3 337
  • 正文 我和宋清朗相戀三年悔耘,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片我擂。...
    茶點故事閱讀 40,117評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡衬以,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出校摩,到底是詐尸還是另有隱情看峻,我是刑警寧澤,帶...
    沈念sama閱讀 35,810評論 5 346
  • 正文 年R本政府宣布衙吩,位于F島的核電站互妓,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏坤塞。R本人自食惡果不足惜冯勉,卻給世界環(huán)境...
    茶點故事閱讀 41,462評論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望尺锚。 院中可真熱鬧珠闰,春花似錦惜浅、人聲如沸瘫辩。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,011評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽伐厌。三九已至承绸,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間挣轨,已是汗流浹背军熏。 一陣腳步聲響...
    開封第一講書人閱讀 33,139評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留卷扮,地道東北人荡澎。 一個月前我還...
    沈念sama閱讀 48,377評論 3 373
  • 正文 我出身青樓,卻偏偏與公主長得像晤锹,于是被迫代替她去往敵國和親摩幔。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 45,060評論 2 355

推薦閱讀更多精彩內(nèi)容

  • 深入理解Emoji(一) —— 字符集鞭铆,字符集編碼深入理解Emoji(二) —— 字節(jié)序和BOM Emoji字符是...
    黎清海閱讀 24,504評論 5 18
  • 某一天或衡,leader找到我說,felix啊车遂,這里有個小需求封断,給我們的實名認證中的地址加入字數(shù)限制,一天時間綽綽有余...
    felix9閱讀 20,398評論 0 15
  • 前言 最先接觸編程的知識是在大學(xué)里面,大學(xué)里面學(xué)了一些基礎(chǔ)的知識衣陶,c語言回梧,java語言,單片機的匯編語言等祖搓;大學(xué)畢...
    oceanfive閱讀 3,087評論 0 7
  • 在當前這個時代(比如說公元2016年)狱意,如果你并不是在維護歷史遺留的文本處理代碼,沒有在每個地方都使用Unicod...
    縱橫而樂閱讀 2,763評論 3 16
  • 之前突然發(fā)現(xiàn)自己對字符編碼還是一知半解拯欧,基本上只是聽說過各種編碼的名字详囤,對它們之間的特點和區(qū)別還是不甚了解。所以這...
    L_Zephyr閱讀 1,929評論 0 4