中文亚洲精品无码_熟女乱子伦免费_人人超碰人人爱国产_亚洲熟妇女综合网

當(dāng)前位置: 首頁(yè) > news >正文

服裝網(wǎng)站建設(shè)規(guī)劃方案佛山今日頭條

服裝網(wǎng)站建設(shè)規(guī)劃方案,佛山今日頭條,香飄飄網(wǎng)站平臺(tái)建設(shè),企業(yè)微網(wǎng)站建設(shè)本文為《人人都能讀標(biāo)準(zhǔn)》—— ECMAScript篇的第12篇。我在這個(gè)倉(cāng)庫(kù)中系統(tǒng)地介紹了標(biāo)準(zhǔn)的閱讀規(guī)則以及使用方式,并深入剖析了標(biāo)準(zhǔn)對(duì)JavaScript核心原理的描述。 ECMAScript有7種原始類(lèi)型,分別是Undefined、Null、Boolean、String、Number、BigInt、Symbo…

本文為《人人都能讀標(biāo)準(zhǔn)》—— ECMAScript篇的第12篇。我在這個(gè)倉(cāng)庫(kù)中系統(tǒng)地介紹了標(biāo)準(zhǔn)的閱讀規(guī)則以及使用方式,并深入剖析了標(biāo)準(zhǔn)對(duì)JavaScript核心原理的描述。


ECMAScript有7種原始類(lèi)型,分別是Undefined、Null、Boolean、String、Number、BigInt、Symbol。

本節(jié)中,我會(huì)先講這7種原始類(lèi)型的創(chuàng)建方式;然后我會(huì)談到從標(biāo)準(zhǔn)的角度看,在原始類(lèi)型上如對(duì)象一般調(diào)用方法是如何實(shí)現(xiàn)的;最后,我會(huì)對(duì)String和Number類(lèi)型的底層編碼形式進(jìn)行深入的講解。


原始類(lèi)型的創(chuàng)建

創(chuàng)建原始類(lèi)型的主要途徑是字面量。我們從字面量表達(dá)式的產(chǎn)生式可以看到,ECMAScript有4種原始類(lèi)型的字面量:

literal-grammar

Null與Boolean

null字面量與Boolean字面量都非常簡(jiǎn)單,一個(gè)只能由終結(jié)符null構(gòu)成,另一個(gè)只能由終結(jié)符truefalse構(gòu)成。


Number與BigInt

數(shù)字字面量是我們?cè)谠砥脕?lái)解釋文法時(shí),舉的一個(gè)重要的例子。你還記得這張我們當(dāng)時(shí)對(duì)數(shù)字字面量文法的“解構(gòu)圖”嗎?

NumericLiteral-destructure

從解構(gòu)的結(jié)果我們可以看到,數(shù)字字面量不僅可以生成Number類(lèi)型,也可以生成BigInt類(lèi)型,總的來(lái)說(shuō),它有5種大的合法結(jié)構(gòu):

  • ①十進(jìn)制數(shù)字:允許純數(shù)字:100.51;也允許以小數(shù)點(diǎn)開(kāi)頭:.0005;還允許使用指數(shù)e:100e-2.5e-3

  • ②十進(jìn)制bigInt:不允許有小數(shù)點(diǎn),也不允許使用指數(shù)e,且必須在數(shù)字后面添加n,如0n、100n

  • ③非十進(jìn)制整數(shù),包括:

    • 二進(jìn)制整數(shù):在二進(jìn)制數(shù)字(0和1)前面在0b0B0b10100B1010

    • 八進(jìn)制整數(shù):在八進(jìn)制數(shù)字(0~7)前面加0o0O0o12、0O12

    • 十六進(jìn)制整數(shù):在十六進(jìn)制數(shù)字(0~9與Aa~Ff)前面加0x0X0x000A0X000a

  • ④非十進(jìn)制bigInt:與非十進(jìn)制整數(shù)一樣,只是后面需要多加一個(gè)n0b1010n、0o12n0x000An;

  • ⑤老式的8進(jìn)制:在八進(jìn)制數(shù)字前面加0來(lái)表示8進(jìn)制:如012、00012,現(xiàn)在這種寫(xiě)法已經(jīng)不被推薦了。

此外,對(duì)于這些不同的數(shù)字字面量具體會(huì)產(chǎn)生什么樣的數(shù)值,標(biāo)準(zhǔn)使用靜態(tài)語(yǔ)義NumericValue來(lái)表示他們的“取值”過(guò)程。


String

我們同樣可以像數(shù)字字面量一樣對(duì)字符串字面量進(jìn)行展開(kāi):

StringLiteral-destructure

從展開(kāi)的結(jié)果看,字符串字面量包括雙引號(hào)字符串以及單引號(hào)字符串,且不包括字符串模版,字符串模版的文法在模版產(chǎn)生式中定義。

雙引號(hào)字符串與單引號(hào)字符串,除了引號(hào)不同,每個(gè)字符的構(gòu)成基本一樣,都是由5條代換式組成,以雙引號(hào)字符為例(圖中框出部分):

  • ①:表示字符可以由除了雙引號(hào)"、行終結(jié)符、以及\以外的所有Unicode字符構(gòu)成,這是我們最常使用的字符;

  • ②:表示行終結(jié)符中的<LS>可以直接作為字符串字符使用;

  • ③:表示行終結(jié)符中的<PS>可以直接作為字符串字符使用;

  • ④:表示那些通過(guò)使用\轉(zhuǎn)義后有特殊含義的字符或字符序列,包括:

    • 單轉(zhuǎn)義字符,包括\b\t、\n、\v\f、\r\"、\'\\。
    • 八進(jìn)制轉(zhuǎn)義序列:使用\\0開(kāi)頭。
    • 十六進(jìn)制轉(zhuǎn)義序列:使用\x開(kāi)頭,且后面只能跟兩個(gè)十六進(jìn)制數(shù)字。
    • 碼點(diǎn)轉(zhuǎn)義序列:使用\u開(kāi)頭,有兩種寫(xiě)法,不帶{}的寫(xiě)法必須跟4個(gè)十六進(jìn)制數(shù)字。

    從對(duì)字符串取值的靜態(tài)語(yǔ)義SV我們可以得知:八進(jìn)制轉(zhuǎn)義序列、十六進(jìn)制轉(zhuǎn)義序列、碼點(diǎn)轉(zhuǎn)義序列最終都會(huì)根據(jù)其數(shù)字的值轉(zhuǎn)化為特定的碼點(diǎn),如下圖所示(如果你對(duì)碼點(diǎn)的概念不熟,后面的字符串編碼形式部分能夠幫到你):

    SV-evaluation

    基于這一點(diǎn),我們可以使用不同的字符串字面量表示同一個(gè)換行符號(hào)\n(碼點(diǎn)為10):

    "\n" === "\012"; // true - 八進(jìn)制轉(zhuǎn)義序列
    "\n" === "\x0A"; // true - 十六進(jìn)制轉(zhuǎn)義
    "\n" === "\u000A" // true - 碼點(diǎn)轉(zhuǎn)義序列(寫(xiě)法1)
    "\n" === "\u{A}" // true - 碼點(diǎn)轉(zhuǎn)義序列(寫(xiě)法2)
    
  • ⑤:第五條代換式是對(duì)行終結(jié)符的轉(zhuǎn)義,這甚至使得你可以不借助字符串模版,直接在字符串中換行:

    console.log("\我完全合法!") 
    

undefined

undefined沒(méi)有字面量文法,因而無(wú)法通過(guò)字面量創(chuàng)建。當(dāng)我們?cè)诖a中如字面量一般地使用undefined時(shí),實(shí)際上,它訪問(wèn)的是全局對(duì)象上的undefined屬性:

// undefined是全局對(duì)象上的屬性
undefined in window // true
// 全局對(duì)象上的undefined屬性不可修改
Object.getOwnPropertyDescriptor(window, "undefined") // {value: undefined, writable: false, enumerable: false, configurable: false}

undefined也不是保留字,所以你可以用undefined作為變量的標(biāo)識(shí)符:

{let undefined = 1 // 聲明一個(gè)名為undefined的變量let a // 未賦值的變量會(huì)初始化值為undefinedconsole.log(a === undefined) // falseconsole.log(a === void 0) // true
}

有的代碼,你會(huì)發(fā)現(xiàn)像這里一樣使用不太常見(jiàn)的void運(yùn)算符,void運(yùn)算符可以用來(lái)獲得“純正”的undefined,我們可以從它的求值語(yǔ)義中得到這個(gè)信息:

void-operator

Symbol

Symbol也沒(méi)有字面量,它只能通過(guò)內(nèi)置對(duì)象Symbol創(chuàng)建:

Symbol("foo")
Symbol.for("foo")

標(biāo)準(zhǔn)中定義了一系列常用的Symbol,這些Symbol常常作為對(duì)象的插件使用。


在原始類(lèi)型上“調(diào)用”方法

我們對(duì)于原始類(lèi)型的方法調(diào)用并不陌生:

10.334524 .toFixed(2) // '10.33'
"  test ".trim() // "test"

原始類(lèi)型之所以可以調(diào)用方法,與成員表達(dá)式MemberExpression的求值語(yǔ)義息息相關(guān)。如果你經(jīng)常讀標(biāo)準(zhǔn),你就會(huì)發(fā)現(xiàn)成員表達(dá)式是一個(gè)存在感非常高的表達(dá)式。

通過(guò)成員表達(dá)式的產(chǎn)生式,我們很容易發(fā)現(xiàn),a.b的形式會(huì)被解析為成員表達(dá)式。

member-expression-grammar

而對(duì)a.b形式的成員表達(dá)式的求值也非常簡(jiǎn)單明了:先獲得.左側(cè)表達(dá)式的值,然后通過(guò)抽象操作 EvaluatePropertyAccessWithIdentifierKey獲得這個(gè)值上對(duì)應(yīng)的屬性:

member-expression-evaluation

這里的“玄機(jī)”來(lái)自于第二步的抽象操作GetValue。不管第一步得到的是不是一個(gè)對(duì)象,GetValue會(huì)把第一步獲得的結(jié)果使用抽象操作ToObject轉(zhuǎn)化為對(duì)象。

getValue

于是,我們?cè)赥oObject中就能看到不同的數(shù)據(jù)類(lèi)型,轉(zhuǎn)換為對(duì)象的結(jié)果:

toObject

在這里,undefined與null無(wú)法進(jìn)行轉(zhuǎn)換,因?yàn)镋CMAScript沒(méi)有設(shè)計(jì)與這兩個(gè)類(lèi)型對(duì)應(yīng)的內(nèi)置對(duì)象,所以在undefined和null頭上使用“成員表達(dá)式”會(huì)報(bào)錯(cuò):

undefined[2]; // ?:Uncaught TypeError: Cannot read properties of undefined (reading '2')
null[2] // ?: Uncaught TypeError: Cannot read properties of null (reading '2')

其他的原始類(lèi)型都會(huì)轉(zhuǎn)化為各自的內(nèi)置對(duì)象,于是,就可以使用各自的內(nèi)置對(duì)象上的方法。

在轉(zhuǎn)化結(jié)果的描述中,不同的對(duì)象都有一個(gè)叫做“內(nèi)部插槽”的東西,使用[[]]表示。關(guān)于內(nèi)部插槽,我會(huì)在13.對(duì)象類(lèi)型進(jìn)行解釋。


String類(lèi)型的編碼形式

String類(lèi)型表示程序中的字符串。而談到字符串,就離不開(kāi)字符集(Character set)字符編碼(Character Encoding) 。

現(xiàn)行世界中主要使用的字符集是Unicode,包含將近15萬(wàn)個(gè)字符。對(duì)于Unicode主要的兩種字符編碼形式分別是UTF-8以及UTF-16。其中HTML默認(rèn)使用的是UTF-8,而ECMAScript默認(rèn)使用的是UTF-16。

不管是使用UTF-8還是UTF-16,都可以表示Unicode中所有的字符。而這里有兩個(gè)重要的概念:

  • 碼點(diǎn)(code point) :字符編碼中,每個(gè)Unicode字符對(duì)應(yīng)的數(shù)字映射。
  • 碼元(code unit) :字符編碼中,碼點(diǎn)的最小組成單位。

在UTF-8中,一個(gè)碼元用一個(gè)字節(jié)(8位)表示,一個(gè)碼點(diǎn)用1到4個(gè)碼元表示;在UTF-16中,一個(gè)碼元用兩個(gè)字節(jié)(16位)表示,一個(gè)碼點(diǎn)用1個(gè)或2個(gè)碼元表示。


UTF-16的編碼模型

在講模型之前,有一個(gè)事情需要先搞清楚。在ECMAScript,數(shù)字類(lèi)型的十六進(jìn)制以0x開(kāi)頭,如0x000A;表示碼點(diǎn)的字符串的十六進(jìn)制以\x\u開(kāi)頭,如"\x0A"、"\u000A",如果你不弄清楚這一點(diǎn),就常常會(huì)被它們寫(xiě)法的切換弄得暈頭轉(zhuǎn)向。

正如前面所說(shuō),在UTF-16中,一個(gè)碼元使用兩個(gè)字節(jié)表示,因此每個(gè)碼元能夠表示的區(qū)間是[0x0000, 0xFFFF]。在這個(gè)區(qū)間內(nèi),UTF-16又劃分出一個(gè)高代理碼元(high-surrogate code unit),區(qū)間為[0xD800,0xDBFF],以及一個(gè)低代理碼元(low-surrogate code unit),區(qū)間為[0xDC00, 0xDFFF],如下圖所示:

code-unit1

在ECMAScript中,碼元是按照以下方式轉(zhuǎn)化為碼點(diǎn)的:

  • 當(dāng)一個(gè)碼元即不是高代理碼元,也不是低代理碼元的時(shí)候,可以直接轉(zhuǎn)化為碼點(diǎn);

  • 當(dāng)連續(xù)的兩個(gè)碼元c1、c2,前一個(gè)位于高代理碼元,后一個(gè)位于低代理碼元的時(shí)候,他們將構(gòu)成一個(gè)代理對(duì)(surrogate pair),并通過(guò)以下的公式計(jì)算出碼點(diǎn)的值:

     (c1 - 0xD800) × 0x400 + (c2 - 0xDC00) + 0x10000
    
  • 其他情況,碼元都會(huì)被直接轉(zhuǎn)化為碼點(diǎn)。

比如,下面的代碼將一個(gè)高代理碼元與一個(gè)低代理碼元組合,得到了新的碼點(diǎn):

console.log("\uD83D" + "\uDE0A')" //  '😊'

code-unit2


UTF-16在實(shí)際代碼中的應(yīng)用

在ECMAScript中,字符串的length方法計(jì)算的是字符串中碼元的數(shù)量,而不是碼點(diǎn)的數(shù)量:

"😊".length // 2
"😊"[0] // '\uD83D'
"😊"[1] // '\uDE0A'

在字符串方法的命名中,ECMAScript習(xí)慣使用charCode表示一個(gè)碼元,使用codePoint表示一個(gè)碼點(diǎn),相關(guān)的方法包括:

  • String.prototype.charCodeAt(pos):返回位置pos上碼元的值。

    "😊".charCodeAt(0) // 55357, 16進(jìn)制表示是0xD83D
    "😊".charCodeAt(1) // 56842, 16進(jìn)制表示是0xDE0A
    
  • String.prototyoe.codePointAt(pos):返回位置pos上碼點(diǎn)的值。

    "😊".codePointAt(0) // 128522
    "😊".codePointAt(1) // 56842
    
  • String.fromCharCode(codeUnit):把碼元轉(zhuǎn)化為字符。

    String.fromCharCode(128522) // ?
    String.fromCharCode(55357, 56842) // 😊
    
  • String.fromCodePoint(codePoint):把碼點(diǎn)轉(zhuǎn)化為字符。

    String.fromCodePoint(128522) // 😊
    String.fromCodePoint(55357, 56842) // 😊
    

在這里,我們甚至還可以使用這些結(jié)果驗(yàn)證前面兩個(gè)碼元拼成一個(gè)碼點(diǎn)的公式:

 (c1 - 0xD800) × 0x400 + (c2 - 0xDC00) + 0x10000

因?yàn)槲覀円呀?jīng)知道,“😊”是由兩個(gè)碼元組成,數(shù)值分別為55357與56842,于是,我們可以在String.fromCodePoint中應(yīng)用這條公式:

String.fromCodePoint((55357 - 0xD800) * 0x400 + (56842 - 0xDC00) + 0x10000) // 😊

Number類(lèi)型的編碼形式

從上面我們可以看出,String類(lèi)型中的每個(gè)字符實(shí)際上是由內(nèi)存中16位或32位二進(jìn)制表示的。而Number類(lèi)型則是使用64位二進(jìn)制表示,具體采用的是《IEEE 754-2019》定義的雙精度浮點(diǎn)數(shù)格式,在其他編程語(yǔ)言中,這種浮點(diǎn)數(shù)類(lèi)型也常用float64表示。


雙精度浮點(diǎn)數(shù)模型

IEEE 754把64位分成3個(gè)部分:

  • 符號(hào)位(sign):占用1位
  • 指數(shù)位(exponent):占用11位
  • 有效數(shù)位(fraction):占用52個(gè)位

懶得做圖了,這里直接使用維基百科提供的圖:

float64-model

在這個(gè)模型中,任意數(shù)字都可以使用以下的公式表示:

float64-formula

在這條公式中,sign表示符號(hào)位,b表示有效數(shù)位,e表示指數(shù)位。

這里需要注意的是:這是一條混合了十進(jìn)制和二進(jìn)制數(shù)字的計(jì)算公式。 中間部分的(1.b51b52...b0)是二進(jìn)制表示,一個(gè)帶有小數(shù)點(diǎn)的二進(jìn)制。后面的2^e-1023是十進(jìn)制數(shù)字,不搞清楚這一點(diǎn),你就無(wú)法得到正確的結(jié)果。

比如,數(shù)字1.5,可以用以下內(nèi)存空間表示(這張圖是我在一個(gè)float64二進(jìn)制轉(zhuǎn)換器中獲得的,這里的Mantissa(尾數(shù))相當(dāng)于上面的fraction(有效數(shù)位)):

float64-example

此時(shí):

  • 符號(hào)位為0,于是符號(hào)部分的計(jì)算相當(dāng)于-1^0,表示正數(shù);
  • 指數(shù)位為01111111111,轉(zhuǎn)為十進(jìn)制后是1023。于是,指數(shù)部分計(jì)算為2^(1023 - 1023),結(jié)果為1;
  • 在有效數(shù)位上,我們得到的是一個(gè)1.1的二進(jìn)制小數(shù),轉(zhuǎn)化為十進(jìn)制的方式以及結(jié)果是2^0 + 2^-1 = 1 + 0.5 = 1.5

所以,最終的計(jì)算結(jié)果為:

(-1^0) * (1.5) * 2^0 = 1.5

按理說(shuō),64位二進(jìn)制應(yīng)該可以表示2^64個(gè)數(shù)字。但實(shí)際上,ECMAScript的數(shù)字只有2^64 - 2^53 + 3種,這是因?yàn)?#xff1a;當(dāng)一個(gè)數(shù)字的指數(shù)位全是1的時(shí)候,被設(shè)計(jì)為不能通過(guò)以上的公式轉(zhuǎn)化為實(shí)際的數(shù)字,這類(lèi)特殊的數(shù)字有2^53個(gè)(1個(gè)符號(hào)位 + 52個(gè)有效數(shù)位)。在ECMAScript中,這類(lèi)特殊的數(shù)字會(huì)被轉(zhuǎn)化為另外3種特殊的值:

  • 如果此時(shí)有效數(shù)位全為0,符號(hào)位也是為0,在ECMAScript表示為+Infinity;
    Infinity

  • 如果此時(shí)有效數(shù)位全為0,符號(hào)位為1,則表示為-Infinity;
    minus-Infinity

  • 除此以外,其他的值都表示為NaN(Not a Number)。

    NaN


精度丟失問(wèn)題

使用浮點(diǎn)數(shù)表示數(shù)字的優(yōu)勢(shì)在于,它能夠表示的數(shù)字范圍比整點(diǎn)數(shù)更廣。但它的缺點(diǎn)在于,有時(shí)候會(huì)有精度丟失的問(wèn)題。稍有經(jīng)驗(yàn)的前端都明白,在JS中,0.1 + 0.2 不精準(zhǔn)等于 0.3,核心原因在于:雙精度浮點(diǎn)數(shù)模型根本無(wú)法精確表示0.1、0.2、0.3。

你完全可以在上面我提供的轉(zhuǎn)換器中測(cè)試一下:把0.3轉(zhuǎn)化成二進(jìn)制,再把對(duì)應(yīng)的二進(jìn)制反向轉(zhuǎn)化一下,得到的只是一個(gè)無(wú)限接近0.3的數(shù)字,而不是0.3本身。

http://www.risenshineclean.com/news/61466.html

相關(guān)文章:

  • 房地產(chǎn)網(wǎng)站制作關(guān)聯(lián)詞有哪些三年級(jí)
  • 什么網(wǎng)站可以做實(shí)驗(yàn)室免費(fèi)源碼網(wǎng)站
  • 順德網(wǎng)站建設(shè)哪家好網(wǎng)頁(yè)設(shè)計(jì)學(xué)生作業(yè)模板
  • 網(wǎng)站建設(shè)能帶來(lái)流量么建站小程序
  • 有哪些網(wǎng)站免費(fèi)做推廣獨(dú)立站seo
  • 深圳網(wǎng)站制作公司興田德潤(rùn)在哪里建立網(wǎng)站平臺(tái)
  • 介紹產(chǎn)品網(wǎng)站制作制作自己的網(wǎng)頁(yè)
  • 操作簡(jiǎn)單網(wǎng)站搭建費(fèi)用網(wǎng)站免費(fèi)搭建平臺(tái)
  • wordpress手機(jī)號(hào)網(wǎng)站企業(yè)seo培訓(xùn)
  • 中國(guó)的網(wǎng)站域名新媒體營(yíng)銷(xiāo)案例分析
  • 程序員做彩票網(wǎng)站違法嗎競(jìng)價(jià)廣告推廣
  • php+開(kāi)發(fā)動(dòng)態(tài)網(wǎng)站開(kāi)發(fā)百度推廣的四種收費(fèi)形式
  • 高端網(wǎng)站鑒賞哈爾濱百度搜索排名優(yōu)化
  • 網(wǎng)站開(kāi)發(fā)外快百度自動(dòng)搜索關(guān)鍵詞軟件
  • 長(zhǎng)沙網(wǎng)紅美食seo型網(wǎng)站
  • 蔬菜基地做網(wǎng)站合適嗎金戈枸櫞酸西地那非片
  • 線上網(wǎng)站開(kāi)發(fā)系統(tǒng)流程網(wǎng)絡(luò)營(yíng)銷(xiāo)的宏觀環(huán)境
  • 河南鄭州暴雨傷亡seo標(biāo)題優(yōu)化分析范文
  • 威海網(wǎng)站建設(shè)是什么seo基礎(chǔ)知識(shí)培訓(xùn)
  • 財(cái)務(wù)咨詢網(wǎng)站模板網(wǎng)站推廣的方式和方法
  • nas服務(wù)器 做網(wǎng)站推廣注冊(cè)app賺錢(qián)平臺(tái)
  • 網(wǎng)站續(xù)費(fèi)管理系統(tǒng)合肥網(wǎng)站排名提升
  • 網(wǎng)站開(kāi)發(fā)學(xué)校推廣網(wǎng)站源碼
  • seo網(wǎng)站做推廣寧德市中醫(yī)院
  • 建英語(yǔ)網(wǎng)站好廣西網(wǎng)站建設(shè)
  • 網(wǎng)站建設(shè)的流程范文1500字百度指數(shù)網(wǎng)
  • 網(wǎng)站建設(shè)屬于什么行業(yè)分類(lèi)網(wǎng)絡(luò)銷(xiāo)售怎么做才能做好
  • 網(wǎng)站建設(shè)高端培訓(xùn)目前引流最好的app
  • 專(zhuān)業(yè)國(guó)外建設(shè)網(wǎng)站遼寧和生活app下載安裝
  • 網(wǎng)站建設(shè) 徐州seo網(wǎng)絡(luò)推廣機(jī)構(gòu)