淺析JavaScript語言類型

文章引用來源
極客時間版權(quán)所有: https://time.geekbang.org/column/article/78884

JavaScript中的每一個值都有它自己的類型床玻,JavaScript規(guī)定了七種語言類型劳景,他們是:

  • Undefined
  • Null
  • Boolean
  • String
  • Number
  • Symbol
  • Object

我們來談?wù)勥@些類型的一部分關(guān)鍵知識點

Undefined和Null

思考這個問題:為什么有的編程規(guī)范要求用 void 0 代替 undefined?

undefined

  1. undefined類型表示未定義坑赡,它的值只有一個:undefined
  2. 任何變量賦值前都是undefined類型奄妨,值為undefined(而不是null)
  3. undefined是一個變量涂籽,而非一個關(guān)鍵字
  4. 需要表達這個值,可以用全局變量undefined砸抛,或者void運算

我們針對第三點來展開討論评雌,得出上述問題的答案。
undefined是一個變量直焙,我們避免無意中被篡改景东,建議使用void 0來獲取undefined(等價于void (0) )。我們一般不會把變量賦值為undefined奔誓,這樣可以保證所有的值為undefined的變量斤吐,都是從未賦值的自然狀態(tài)。

void運算

語法:void express 或者 void (express)
void運算符所做的是厨喂,執(zhí)行表達式express和措,然后不論表達式是否有返回值,一律返回undefined蜕煌。
void運算符如果使用括號派阱,括號內(nèi)必須有表達式,如果是void()會被視為執(zhí)行名為void的函數(shù)斜纪,報錯:SyntaxError贫母。

死鏈接

我們有時候會用href="#"來表示死鏈接,但是這樣會導致頁面跳到最上面的視圖盒刚,#包含了一個位置信息腺劣,默認的錨是#top,也就是網(wǎng)頁的上端因块。在頁面很長的時候會使用#來定位頁面的具體位置橘原,格式為:#+id

href=javascript:void(0)用來禁止a標簽的跳轉(zhuǎn)行為,javascript:是偽協(xié)議贮聂,表示url的內(nèi)容通過JavaScript執(zhí)行靠柑,void(0)表示不作任何操作寨辩。

<a href="javascript: void(0)" onClick="window.open()"><!--點擊鏈接后頁面不動吓懈,只打開鏈接-->
<a href="#" onClick="javascript: return false"><!--作用一樣-->

Null

  1. 只有一個值,就是null
  2. 表示空值靡狞,是關(guān)鍵字耻警,可以放心使用null關(guān)鍵字來獲取null值。

String

  1. string的意義并非“字符串”,而是字符串的UTF16編碼甘穿,字符串的最大長度實際上是受字符串編碼長度影響的腮恩。最大長度:253 - 1 。
  2. 字符串是永遠無法變更的温兼,一旦字符串被構(gòu)造出來秸滴,無法用任何方式改變字符串的內(nèi)容。
  3. 字符串把每個UTF16單元當做一個字符來處理募判,所以處理非BMP(超出 U+0000 - U+FFFF 范圍)的字符時荡含,應(yīng)該格外小心。這個設(shè)計繼承自Java届垫,現(xiàn)實中很少用到BMP之外的字符释液。

Number

思考下面問題:為什么在 JavaScript 中,0.1+0.2 不等于0.3

  1. number類型有264- 253+3 個值装处。
  2. 基本符合 IEEE 754-2008 規(guī)定的雙精度浮點數(shù)規(guī)則误债,但也有額外幾個表達的語言場景(比如不讓除以0出錯诗茎,引入了無窮大)逸嘀。
    • NaN阅茶,占用了 9007199254740990未巫,這原本是符合 IEEE 規(guī)則的數(shù)字
    • Infinity阱驾,無窮大
    • -Infinity臀稚,負無窮大
  3. 有+0和-0吊趾,加法運算中沒有區(qū)別彩库,但是除法要區(qū)分形帮,“忘記檢測除以 -0槽惫,而得到負無窮大”的情況經(jīng)常會導致錯誤,而區(qū)分 +0 和 -0 的方式辩撑,正是檢測 1/x 是 Infinity還是-Infinity
  4. 根據(jù)雙精度浮點數(shù)定義界斜,有效的整數(shù)范圍是 -0x1fffffffffffff 至 0x1fffffffffffff,無法精確表示此范圍外的整數(shù)合冀。
  5. 根據(jù)雙精度浮點數(shù)定義各薇,非整數(shù)的Number類型無法用==來比較(三個等號也不行),正確的比較方法是用JavaScript提供的最小精度值:
console.log( 0.1 + 0.2 == 0.3);//false
//正確的比較方法
console.log( Math.abs(0.1 + 0.2 - 0.3) <= Number.EPSILON);//true

Symbol

  1. 表示獨一無二的值君躺,它是一切非字符串的對象key的集合峭判。
  2. Symbol 值通過Symbol函數(shù)生成。這就是說棕叫,對象的屬性名現(xiàn)在可以有兩種類型林螃,一種是原來就有的字符串,另一種就是新增的 Symbol 類型俺泣。凡是屬性名屬于 Symbol 類型疗认,就都是獨一無二的完残,可以保證不會與其他屬性名產(chǎn)生沖突。

Symbol函數(shù)可以接受一個字符串作為參數(shù)横漏,表示對 Symbol 實例的描述谨设,但是即使描述相同,Symbol值也不相等缎浇。

let s1 = Symbol('foo');
let s2 = Symbol('foo');

s1 === s2 // false
  1. 一些標準中提到的 Symbol扎拣,可以在全局的 Symbol 函數(shù)的屬性中找到。例如素跺,我們可以使用 Symbol.iterator 來自定義 for…of 在對象上的行為:
var o = new Object

    o[Symbol.iterator] = function() {
        var v = 0
        return {
            next: function() {
                return { value: v++, done: v > 10 }
            }
        }        
    };

    for(var v of o) 
        console.log(v); // 0 1 2 3 ... 9

Object

問題:為什么給對象添加的方法能用在基本類型上鹏秋?

  1. JavaScript對象的定義是“屬性的集合”。屬性分為數(shù)據(jù)屬性和訪問器屬性亡笑,二者都是 key-value 結(jié)構(gòu)侣夷,key可以是字符串或者Symbol類型。
  2. JavaScript的“類”僅僅是運行時對象的一個私有屬性仑乌,而JavaScript中是無法自定義類型的百拓。
  3. Number、String 和 Boolean晰甚,三個構(gòu)造器是兩用的衙传,當跟 new 搭配時,它們產(chǎn)生對象厕九,當直接調(diào)用時蓖捶,它們表示強制類型轉(zhuǎn)換。
  4. Symbol 函數(shù)比較特殊扁远,直接用 new 調(diào)用它會拋出錯誤俊鱼,但它仍然是Symbol對象的構(gòu)造器。
  5. 我們在原型上添加方法畅买,都可以應(yīng)用于基本類型并闲。
    Symbol.prototype.hello = () => console.log("hello");

    var a = Symbol("a");
    console.log(typeof a); //symbol,a 并非對象
    a.hello(); //hello谷羞,有效

上述問題的答案是:運算符提供了裝箱操作帝火,它會根據(jù)基礎(chǔ)類型構(gòu)造一個臨時對象,使得能夠在基礎(chǔ)類型上調(diào)用對應(yīng)對象的方法湃缎。

裝箱和拆箱

裝箱轉(zhuǎn)換:基本類型-->對象

  • 每一種基本類型犀填,都在對象中有對應(yīng)的類,裝箱機制會頻繁產(chǎn)生臨時對象嗓违。
  • 使用object函數(shù)九巡,可以顯示調(diào)用裝箱能力。
  • 每一類裝箱對象皆有私有的 Class 屬性靠瞎,這些屬性可以O(shè)bject.prototype.toString 獲取比庄。在 JavaScript 中求妹,沒有任何方法可以更改私有的Class 屬性乏盐,因此 Object.prototype.toString 是可以準確識別對象對應(yīng)的基本類型的方法佳窑,它比 instanceof 更加準確。
  • call函數(shù)本身會產(chǎn)生裝箱操作父能,需要配合typeof來區(qū)分基本類型還是對象類型神凑。

拆箱轉(zhuǎn)換:對象-->基本類型

  • ToPrimitive 函數(shù),它是對象類型到基本類型的轉(zhuǎn)換
  • 拆箱轉(zhuǎn)換會嘗試調(diào)用 valueOf 和 toString 來獲得拆箱后的基本類型何吝。如果valueOf 和 toString都不存在溉委,或者沒有返回基本類型,則會產(chǎn)生TypeError爱榕。

對象的運算

    var o = {
        valueOf : () => {console.log("valueOf"); return {}},
        toString : () => {console.log("toString"); return {}}
    }

    o * 2
    // valueOf
    // toString
    // TypeError

String的拆箱

    var o = {
        valueOf : () => {console.log("valueOf"); return {}},
        toString : () => {console.log("toString"); return {}}
    }

    o + ""
    // toString
    // valueOf
    // TypeError

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末瓣喊,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子黔酥,更是在濱河造成了極大的恐慌藻三,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,348評論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件跪者,死亡現(xiàn)場離奇詭異棵帽,居然都是意外死亡,警方通過查閱死者的電腦和手機渣玲,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,122評論 2 385
  • 文/潘曉璐 我一進店門逗概,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人忘衍,你說我怎么就攤上這事逾苫。” “怎么了枚钓?”我有些...
    開封第一講書人閱讀 156,936評論 0 347
  • 文/不壞的土叔 我叫張陵隶垮,是天一觀的道長。 經(jīng)常有香客問我秘噪,道長狸吞,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,427評論 1 283
  • 正文 為了忘掉前任指煎,我火速辦了婚禮蹋偏,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘至壤。我一直安慰自己威始,他們只是感情好,可當我...
    茶點故事閱讀 65,467評論 6 385
  • 文/花漫 我一把揭開白布像街。 她就那樣靜靜地躺著黎棠,像睡著了一般晋渺。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上脓斩,一...
    開封第一講書人閱讀 49,785評論 1 290
  • 那天木西,我揣著相機與錄音,去河邊找鬼随静。 笑死八千,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的燎猛。 我是一名探鬼主播恋捆,決...
    沈念sama閱讀 38,931評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼重绷!你這毒婦竟也來了沸停?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,696評論 0 266
  • 序言:老撾萬榮一對情侶失蹤昭卓,失蹤者是張志新(化名)和其女友劉穎愤钾,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體葬凳,經(jīng)...
    沈念sama閱讀 44,141評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡绰垂,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,483評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了火焰。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片劲装。...
    茶點故事閱讀 38,625評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖昌简,靈堂內(nèi)的尸體忽然破棺而出占业,到底是詐尸還是另有隱情,我是刑警寧澤纯赎,帶...
    沈念sama閱讀 34,291評論 4 329
  • 正文 年R本政府宣布谦疾,位于F島的核電站,受9級特大地震影響犬金,放射性物質(zhì)發(fā)生泄漏念恍。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,892評論 3 312
  • 文/蒙蒙 一晚顷、第九天 我趴在偏房一處隱蔽的房頂上張望峰伙。 院中可真熱鬧,春花似錦该默、人聲如沸瞳氓。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,741評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽匣摘。三九已至店诗,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間音榜,已是汗流浹背庞瘸。 一陣腳步聲響...
    開封第一講書人閱讀 31,977評論 1 265
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留囊咏,地道東北人恕洲。 一個月前我還...
    沈念sama閱讀 46,324評論 2 360
  • 正文 我出身青樓塔橡,卻偏偏與公主長得像梅割,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子葛家,可洞房花燭夜當晚...
    茶點故事閱讀 43,492評論 2 348

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

  • JavaScript語言精粹 前言 約定:=> 表示參考相關(guān)文章或書籍; JS是JavaScript的縮寫户辞。 本書...
    微笑的AK47閱讀 578評論 0 3
  • ??引用類型的值(對象)是引用類型的一個實例底燎。 ??在 ECMAscript 中,引用類型是一種數(shù)據(jù)結(jié)構(gòu)弹砚,用于將數(shù)...
    霜天曉閱讀 1,042評論 0 1
  • 1 語義類標簽(CSS部分) 1.1 定義 ?如section双仍、nav、p桌吃,div朱沃,span,特點是視覺表現(xiàn)上互相...
    RingoD閱讀 478評論 0 1
  • 寒枝冷院雨聲切茅诱, 燈火連窗未有別逗物。 茶氣曛得身意暖, 流光只在此中歇瑟俭。 七絕翎卓,平起首韻,新韻摆寄。
    一沓雪泥閱讀 248評論 0 11
  • 昨天哭著看完了那部被名字耽誤了的電影-三傻失暴。 將近三小時的電影,有捧腹大笑微饥, 更多的是淚流滿面逗扒。 有多久沒有這么痛...
    風似秋閱讀 180評論 1 1