超碰人人人人人,亚洲AV午夜福利精品一区二区,亚洲欧美综合区丁香五月1区,日韩欧美亚洲系列

LOGO OA教程 ERP教程 模切知識(shí)交流 PMS教程 CRM教程 開發(fā)文檔 其他文檔  
 
網(wǎng)站管理員

字母a的6種表示方法,以及其背后的編碼知識(shí)

freeflydom
2025年2月19日 10:33 本文熱度 1151

前言

字符是我們編寫程序的基礎(chǔ)的基礎(chǔ)。

我們前端是最常見的字符,符號(hào),數(shù)字,英文,中文, 我們通常都是使用直接量來表示,偶爾會(huì)在正則表達(dá)等場(chǎng)景用到UTF-16碼點(diǎn)的格式,問題來了,那你知道JS有幾種字符表示方式嗎?

答案:至少6種,以字符a為例子:

`a`        // 'a'
'a'        // 'a'
'\a'       // 'a'
'\141'     // 'a'
'\x61'     // 'a'
'\u0061'   // 'a'
'\u{0061}' // 'a'

前三種都很理解, 后面這又是\\x\u\u{}, 這都是什么玩意?

特別申明: 測(cè)試代碼最新版chrome上執(zhí)行。

先看總結(jié)

格式示例碼點(diǎn)范圍注意
\8進(jìn)制'\141'0-255模板字符串中不可直接使用
\x兩位16進(jìn)制'\x61'0-255必須兩位
\u四位16進(jìn)制'\u0061'0-65535必須四位
\u{16進(jìn)制}'\u{0061}'0-0x10FFFF碼點(diǎn)大于0xFFFF,length為2,下標(biāo)訪問值是高低位的值

編碼基礎(chǔ)知識(shí)

完全理解字符表示,還是需要一些簡(jiǎn)單的編碼知識(shí),我們一起來看看吧。

ASCII 碼

ASCII 碼一共定義了 128 個(gè)字符,例字母 a 是 97 (0110 0001)。這 128 個(gè)字符只使用了 8 位二進(jìn)制數(shù)中的后面 7 位,最前面的一位統(tǒng)一規(guī)定為 0。

ASCII 碼止共定義了128個(gè)字符,其中33個(gè)字符無法顯示。0010 0000 ~ 0111 1110 (32-126)是可以顯示的 ,基本都能使用鍵盤打出來, 具體參見對(duì)照表: ASCII編碼對(duì)照表。

ASCII 額外擴(kuò)展的版本 EASCII,這里就可以使用一個(gè)完整子節(jié)的 8 個(gè) bit 位表示共 256 個(gè)字符,其中就又包括了一些衍生的拉丁字母。 可以參見 extended-ascii-table?。

Unicode 和 碼點(diǎn)

Unicode是字符集, 為了兼容ASCII,Unicode規(guī)定前0-127個(gè)字符是和ASCII是一樣的,不一樣的是128-255這一部分。

我們一起看看ASCII 128-255部分:

 再看看 Unicode的 128-255部分:

其給某個(gè)字符規(guī)定對(duì)應(yīng)的數(shù)值,我們經(jīng)常稱其為碼點(diǎn)。我們可以通過字符串的實(shí)例方法charCodeAtcodePointAt獲取,前者只能準(zhǔn)確獲取碼點(diǎn)值小于0xFFFF(65535)的碼點(diǎn)。

'??'.codePointAt(0)  // 131104 0x20020  正確
'??'.charCodeAt(0)   // 55360  0xd840   錯(cuò)誤
'a'.charCodeAt(0)    // 97     0x0061   正確

對(duì)應(yīng)的我們可以使用String的靜態(tài)方法fromCharCode,fromCodePoint用碼點(diǎn)獲取對(duì)應(yīng)的字符。

String.fromCodePoint(131104)  // "??" 正確
String.fromCharCode(131104)   // " "  錯(cuò)誤
String.fromCharCode(97)       // "a"  正確

UTF-8, UTF-16

我們平時(shí)接觸比多的就是UTF-8和UTF-16,均是Unicode字符編寫的一種實(shí)現(xiàn)。 我們JS編碼的字符串是UTF-16格式來存儲(chǔ)的和表示的。

UTF-16對(duì)于碼點(diǎn)小于0xFFFF的用2個(gè)字節(jié)(1個(gè)編碼單元)表示,大于0xFFFF的編碼用四個(gè)字節(jié)(2個(gè)編碼單元)表示。 具體的體現(xiàn)可以表現(xiàn)在字符的長(zhǎng)度上。

"??".length  // 2  碼點(diǎn) 131104(0x20020)> 65535 (0xFFFF)
"a".length   // 1
"人".length  // 1

這里強(qiáng)調(diào) 0xFFFF 是分界線,很重要。

進(jìn)制轉(zhuǎn)換

我們可以使用數(shù)字實(shí)例toString()10進(jìn)制轉(zhuǎn)為相對(duì)應(yīng)的進(jìn)制。

97..toString(16) // 61
97..toString(2)  // 1100001

下面進(jìn)入正題, 一起來看字符的表示:

\ + 字符

\ 是一個(gè)特殊的存在,轉(zhuǎn)義字符,大多數(shù)情況下,不產(chǎn)生什么作用。 只對(duì)一些特殊的字符起作用。

從下可以看出\a這個(gè)\沒有任何作用,對(duì)\r就不一樣了。

更多轉(zhuǎn)義字符知識(shí),參見 轉(zhuǎn)義字符-維基

\ + 八進(jìn)制

其能表示的碼點(diǎn)范圍值為 0-255。

這里提個(gè)問題, 這里顯示的ASCII的字符,還是Unicode的字符。

  1. 比如字符 a 為 97, 可以使用charCodeAt獲取,
'a'.charCodeAt(0) // 97
  1. 轉(zhuǎn)為8進(jìn)制為97..toString(8) = 141
  2. \141
console.log('\141')  // a

我們看一些特殊碼點(diǎn)的字符,因?yàn)榇a點(diǎn)為31和127的字符,不能被顯示或者表示。

// 37 = 31..toString(8) 
'\37' // '\x1F'
// 177 = 127..toString(8) 
'\177'  // '\x7F'

至于為什么 \177 變?yōu)榱?nbsp;\x7F, 是不是有點(diǎn)疑惑,其實(shí)也很簡(jiǎn)單。 當(dāng)程序檢查其值,不在可顯示范圍的時(shí)候,直接反向計(jì)算其原值,并轉(zhuǎn)為16進(jìn)制值,并使用\x兩位十六進(jìn)制格式表示。

// 177 = 127..toString(8) 
'\177'  // '\x7F'
127.toString(16) // 7f

關(guān)于表示碼點(diǎn)上限(255):

'\377'  // "?"   --- 碼點(diǎn)255 
'\400'  // ' 0'  --- 碼點(diǎn)256  // 大于255可以理解為 '\40' + '0'

回答開始的提問:
我們這里顯示的肯定是Unicode字符啊,前面提過了, JS字符編碼采用的是UTF-16啊。 可以用碼點(diǎn)在128-255的一個(gè)字符試試, 那就碼點(diǎn)254的字符吧:

擴(kuò)展 ASCII 254: 
Unicode 254: 't'

//376 = 254..toString(8)
'\376'  // 't'

所以大家要明白,我們這各種字符表示方法,表示的都是Unicode字符。

關(guān)于\x兩位十六進(jìn)制格式,我們開講。

\x + 兩位十六進(jìn)制

我們可以用0x表示16進(jìn)制的數(shù)字,所以\x大家也很好理解,是16進(jìn)制。

0x61    // 97  0x表示16進(jìn)制格式數(shù)字
'a'.charCodeAt(0)  // 獲取碼點(diǎn)   97
97..toString(16)   // 轉(zhuǎn)為16進(jìn)制 61
'\x61'  // 'a'

兩位十六進(jìn)制碼點(diǎn), 0x00 ~ 0xFF(0~255) , 和 \八進(jìn)制碼一樣,不可顯示的碼點(diǎn)字符,直接顯示其編碼

// 1f = 31..toString(16)
'\x1F' // '\x1F'
// 20 = 32..toString(16)
'\x20' // ' '
// 7e = 126..toString(16)
'\x7e' // '~'
// 7f = 127..toString(16)
'\x7f' // '\x7F'
// 80 = 128..toString(16)
'\x80' // '\x80'

到這里你可能問,你這里,那么這不能顯示,那不能顯示,有沒有一個(gè)表啊。有的, 參見 Unicode碼表, 這里記錄了 0x0000 到 0xFFFF的碼點(diǎn)的字符,一般情況準(zhǔn)夠用。

0-255碼點(diǎn)范圍內(nèi), 0x00 到 0x1F(0-31), 0x80 到 0x9F(128-159)是無法顯示的或者看不見的。 

'\x9F'  // '\x9F'   // 編碼輸出
'\xA1'  // "?"     // 正常

這個(gè)結(jié)果,在不通瀏覽器,可能輸出還不一樣。 盡量采用最新版本的chrome去驗(yàn)證。

雖然輸出的顯示有些區(qū)別,但是都表示這玩意不能表示一個(gè)字符,請(qǐng)自重。

360瀏覽器:

firefox:

chrome:

\u + 四位十六進(jìn)制

這里固定是4位,少一位都不行。

"\u0061" // "a"
"\u061"  // 報(bào)錯(cuò)

還是4位,如果多了, 截取前4位,后面的直接追加。看個(gè)例子,非常好理解。

'\u0061'   // 'a'
'\u00610'  // 'a0'

這里也就反應(yīng)了問題,碼點(diǎn)大于0xFFFF,大于4位16進(jìn)制的字符怎么表示???

ES6考慮了這個(gè)問題,于是推出了 \u{ + 十六進(jìn)制 + }, 看下個(gè)章節(jié)。

我們之前說過,UTF-16是Unicode的一種實(shí)現(xiàn),Unicode的代理區(qū) 0xD800-0xDFFF, 其不代表任何字符。同理,我們采用\u + 四位十六進(jìn)制方式,如果碼點(diǎn)在這個(gè)區(qū)間,返回 ?或者原字符(瀏覽器不同,可能返回不同), 當(dāng)然其他的碼點(diǎn)也可能還沒設(shè)定值或者是不可打印的。

'\uD800'  // '\uD800' 
'\uDFFF'  // '\uD800'

實(shí)際上 UTF-16也就是利用了代理區(qū),把碼點(diǎn)大于0xFFFF字符分為高低兩部分, 索引值0獲得的值實(shí)際上是高位部分,索引值1獲得的是低位部分。

var text = "??";
text[0]  //  '\uD840'
text[1]  //  '\uDC20'

更多utf-16編碼的知識(shí),我們后續(xù)跟上。

\u{ + 十六進(jìn)制 + }

ES6新增的能力。 這個(gè)多了一個(gè){}包裹。
這個(gè)應(yīng)該是可以一統(tǒng)江湖,可以表示碼點(diǎn)低于0xFFFF的字符,也可表示碼點(diǎn)大于0xFFFF的字符。

"\u{20020}"  // '??'
"\u{0061}"   // 'a'
"\u{061}"    // 'a'
"\u{61}"     // 'a'
"\u{9}"      // "\t"

而且其還沒有強(qiáng)制四位的限制,簡(jiǎn)直爽的沒法沒邊。

缺點(diǎn)嘛,那就是兼容性了,就讓時(shí)間去磨平吧。

ES6的模板字符串

ES6的模板字符串,可以說是爽歪歪,我們就也算其一種新的字符表示方式吧。

我們也是可以使用\u, \u{}\x格式的

// 61 = "a".charCodeAt(0).toString(16)
`我\u{61}`  // 我a
`我\x61`    // 我a
`我\u0061`  // 我a
`我\a`      // 我a

到這里,你們沒覺得少了了點(diǎn)什么嗎? 沒錯(cuò) \8進(jìn)制,是不被允許的

// 141 = "a".charCodeAt(0).toString(8)
`我\141`

如果,你非得用,那就 ${''}包裹一下:

`我${'\141'}`   // '我a'

實(shí)際的應(yīng)用

匹配中文的正則

我們總不能去羅列,多義采取的是[\u4e00-\u9fa5]這種格式去匹配:

var regZH = /[\u4e00-\u9fa5]/g;
regZH.test("a");   // false
regZH.test("人");  // true
regZH.test("??");  // false  尷尬了不

這里注意了,只能識(shí)別常見中文。, 畢竟碼點(diǎn)的范圍就那么大點(diǎn)。

去掉空白字符

看看MDN上 String.prototype.trim

if (!String.prototype.trim) {
  String.prototype.trim = function () {
    return this.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, '');
  };
}

我們一起來看一下著名的core-js對(duì)trim的空白字符的理解 whitespaces.js

module.exports = '\u0009\u000A\u000B\u000C\u000D\u0020\u00A0\u1680\u2000\u2001\u2002' +
  '\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200A\u202F\u205F\u3000\u2028\u2029\uFEFF';

我們還是輸出一下吧:

'\u0009\u000A\u000B\u000C\u000D\u0020\u00A0\u1680\u2000\u2001\u2002' +
  '\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200A\u202F\u205F\u3000\u2028\u2029\uFEFF'
 //  '\t\n\v\f\r  ?????????????? ???' 

CSS content屬性 和 CSS 字體圖標(biāo)

現(xiàn)代瀏覽器,已經(jīng)支持中文,但是建議還是使用\16進(jìn)制編碼格式 。
這里使用的是 \16進(jìn)制, 不需要u也不需要{}, 支持碼點(diǎn)大于0xFFFF的字符

    div.me::before {
        content: "\6211";  // 我
        padding-right: 10px;
    }
    
     div.me::before {
        content: "\20020:";  // ??
        padding-right: 10px;
    }

CSS顏色色值

字體顏色,背景顏色,邊框顏色等等,其有一種表示方式就是6位16進(jìn)制,當(dāng)然也有簡(jiǎn)寫形式。

.title {
    color: #FFF
}

字符個(gè)數(shù)統(tǒng)計(jì)

這個(gè)是利用了UTF-16編碼特性。 因?yàn)?code style="font-family: Menlo, Monaco, Consolas, "Courier New", monospace; font-size: 0.87em; word-break: break-word; border-radius: 2px; overflow-x: auto; background-color: rgb(255, 245, 245); color: rgb(255, 80, 44); padding: 0.065em 0.4em;">\uD800-\DFFF是代理區(qū),具體UTF-16編碼的東西,單獨(dú)來講解。 也可以看見文章 為什么一定是?, 里面有完整的解釋。

const spRegexp = /[\uD800-\uDBFF][\uDC00-\uDFFF]/g;
function chCounts(str){
  return str.replace(spRegexp, '_').length;
}
chCounts("??")  // 1
"??".length // 2

ES6中的方式就多一些了:

Array.from("??").length //1
[..."??"].length  // 1

文件類型識(shí)別

具體可以參見阿寶哥的 JavaScript 如何檢測(cè)文件的類型?

const isPNG = check([0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a]); // PNG圖片對(duì)應(yīng)的魔數(shù)
const realFileElement = document.querySelector("#realFileType");
async function handleChange(event) {
  const file = event.target.files[0];
  const buffers = await readBuffer(file, 0, 8);
  const uint8Array = new Uint8Array(buffers);
  realFileElement.innerText = `${file.name}文件的類型是:${
    isPNG(uint8Array) ? "image/png" : file.type
  }`;
}

其他

  • emoji圖標(biāo)
  • 編碼轉(zhuǎn)換,比如utf-8轉(zhuǎn)base64
  • 等等

轉(zhuǎn)自https://juejin.cn/post/7033184851494699022


該文章在 2025/2/19 10:33:51 編輯過
關(guān)鍵字查詢
相關(guān)文章
正在查詢...
點(diǎn)晴ERP是一款針對(duì)中小制造業(yè)的專業(yè)生產(chǎn)管理軟件系統(tǒng),系統(tǒng)成熟度和易用性得到了國(guó)內(nèi)大量中小企業(yè)的青睞。
點(diǎn)晴PMS碼頭管理系統(tǒng)主要針對(duì)港口碼頭集裝箱與散貨日常運(yùn)作、調(diào)度、堆場(chǎng)、車隊(duì)、財(cái)務(wù)費(fèi)用、相關(guān)報(bào)表等業(yè)務(wù)管理,結(jié)合碼頭的業(yè)務(wù)特點(diǎn),圍繞調(diào)度、堆場(chǎng)作業(yè)而開發(fā)的。集技術(shù)的先進(jìn)性、管理的有效性于一體,是物流碼頭及其他港口類企業(yè)的高效ERP管理信息系統(tǒng)。
點(diǎn)晴WMS倉(cāng)儲(chǔ)管理系統(tǒng)提供了貨物產(chǎn)品管理,銷售管理,采購(gòu)管理,倉(cāng)儲(chǔ)管理,倉(cāng)庫(kù)管理,保質(zhì)期管理,貨位管理,庫(kù)位管理,生產(chǎn)管理,WMS管理系統(tǒng),標(biāo)簽打印,條形碼,二維碼管理,批號(hào)管理軟件。
點(diǎn)晴免費(fèi)OA是一款軟件和通用服務(wù)都免費(fèi),不限功能、不限時(shí)間、不限用戶的免費(fèi)OA協(xié)同辦公管理系統(tǒng)。
Copyright 2010-2025 ClickSun All Rights Reserved