面試題:['1', '2', '3'].map(parseInt) 輸出什么?

配圖源自 Freepik

一蓄诽、背景

事情經(jīng)過是這樣的薛训,前幾天上班路上,跟往常一樣拿起手機看頭條仑氛、逛知乎乙埃、刷掘金嘛。

過程中锯岖,看到以下這個面試題:

['1', '2', '3'].map(parseInt) 輸出什么介袜?

其實,這題很簡單出吹,不就是類似 [0, 1, 2].filter(Boolean) 這種變形題目嘛遇伞,但我卻沒能馬上說出答案。

我知道 parseInt() 的第二個參數(shù)跟進制數(shù)相關(guān)捶牢,但由于平常多數(shù)是缺省第二個參數(shù)鸠珠,平常寫項目也會啟用 ESLint 的 radix 規(guī)則,但規(guī)則啟用時也幾乎是填寫 10 作為實參秋麸,因為涉及其他進制數(shù)的情況確實很少很少...

所以渐排,趁機再熟悉下 parseInt(string, radix) 這個函數(shù),也是挺不錯的竹勉。

回到上面的題目飞盆,分解一下,就是返回以下三個運算結(jié)果組成的數(shù)組嘛:

parseInt('1', 0, ['1', '2', '3'])
parseInt('2', 1, ['1', '2', '3'])
parseInt('3', 2, ['1', '2', '3'])

對于 parseInt() 函數(shù),僅接收兩個參數(shù)吓歇,所以第三個參數(shù)實際上沒有任何作用孽水,因此 ['1', '2', '3'].map(parseInt) 結(jié)果就是:

[
  parseInt('1', 0),
  parseInt('2', 1),
  parseInt('3', 2)
]

但這篇文章的重點并非是答案,我們應(yīng)該關(guān)注 parseInt(string, radix) 函數(shù)本身城看。

二女气、八進制數(shù)表示法的前世今生

如果常用 ESLint 的同學(xué),應(yīng)該知道它有一個規(guī)則 radix 是跟 parseInt() 相關(guān)的测柠。

看個例子炼鞠,它們分別打印什么結(jié)果?

parseInt('071') // 57
parseInt('071', 10) // 71

有些本著求真的同學(xué)轰胁,將 parseInt('071') 拷到控制臺發(fā)現(xiàn)谒主,無論是 Chrome、Firefox 還是 Safari 都是打印出 71 而不是 57赃阀。

我為什么寫成 57 呢霎肯?是寫錯了嗎?明明在瀏覽器中 parseInt('071') 都是打印出 71 呢榛斯!

先別急观游,我們知道在「嚴格模式」下,是不允許使用以 0 開頭的八進制語法的驮俗。

"use strict"
var n = 071 // SyntaxError: Octal literals are not allowed in strict mode.

但我想懂缕,你有可能不知道的是,其實在 ES6 標準發(fā)布之前王凑,ECMAScript 是沒有八進制語法的搪柑,至于類似 071 這種八進制表示法它只是被所有瀏覽器廠商支持罷了。就好比如 Object.prototype.__proto__ 從來就不是 ECMAScript 的標準語法一樣索烹,但所有瀏覽器都支持罷了拌屏,標準語法是 Object.getPrototypeOf()

在 ES6 中提供了八進制數(shù)的標準規(guī)范:在數(shù)字前加上 0o 來表示八進制數(shù)术荤,比如八進制的 710o71 表示。

回到 parseInt(string, radix) 與八進制的話題上每篷,

當沒有指定 radix 參數(shù)時瓣戚,看看各家是如何解析八進制數(shù)的?

  • ES3「不提倡」將帶有 0 開頭的數(shù)值字符串解析為一個八進制焦读。(不贊成子库,但沒禁止)
  • ES5 規(guī)范中「不允許」parseInt 函數(shù)的實現(xiàn)環(huán)境把帶有 0 開頭的數(shù)值字符串解析為八進制數(shù)值,而是以 10 為基數(shù)(即十進制)進行解析矗晃。(規(guī)范禁止了仑嗅,但瀏覽器沒有按標準實現(xiàn))
  • 各瀏覽器廠商大爺們:我偏不按你規(guī)范去實現(xiàn),仍要把帶有 0 開頭的數(shù)值字符串解析成八進制數(shù)值。(我行我素)

本著求真的態(tài)度仓技,拿出了上古神器去驗證并得出結(jié)果:在 IE8 及以下瀏覽器 parseInt('071') 打印結(jié)果為 57(下圖)鸵贬,而 IE9 及以上則為 71

Internet Explorer 8

隨著 JavaScript 的飛速發(fā)展脖捻,瀏覽器廠商們都向標準靠近了阔逼,不再肆意我行我素了。至于瀏覽器 parseInt('071') 打印結(jié)果是 71地沮,原因正是現(xiàn)在的瀏覽器 JS 引擎是以 10 為基數(shù)進行解析了嗜浮。

盡管 2022 年了,但仍要兼容舊版(遠古)瀏覽器摩疑,所以顯式指定 radix 參數(shù)是非常有必要的危融。本節(jié)用一個比較典型的案例來說明,使用 parseInt 函數(shù)時雷袋,應(yīng)當指定 radix 參數(shù)吉殃。

在 JavaScript 中,有四種進制數(shù)的表示語法:

  • 十進制:沒有「前導(dǎo)零」的數(shù)值片排。
  • 二進制:以 0b0B 開頭的數(shù)值寨腔。
  • 八進制:以 0o0O 開頭的數(shù)值。瀏覽器等宿主環(huán)境也支持以「前導(dǎo)零」開頭率寡,且只有 0 ~ 7 的數(shù)組表示八進制數(shù)迫卢。
  • 十六進制:以 0x0X 開頭的數(shù)值。

三冶共、parseInt

語法

parseInt(string, radix)

解析一個字符串并返回指定基數(shù)的「十進制整數(shù)」或者 NaN乾蛤。

  • string
    被解析的值。若參數(shù)不是字符串類型捅僵,內(nèi)部先隱式類型轉(zhuǎn)換為字符串類型(即調(diào)用相應(yīng)值的 toString() 方法)

  • radix(可選家卖,取值范圍 2 ~ 36 的整數(shù))
    表示字符串的基數(shù)。但請注意庙楚,10 不是默認值上荡!當參數(shù) radix 缺省時,會有幾種情況馒闷,下面會介紹酪捡。

注意點

  1. string 參數(shù)帶有前導(dǎo)或尾隨空白符(包括 \n\r纳账、\f逛薇、\t\v 和空格)疏虫,它們將會被忽略永罚。換句話說啤呼,實際有意義的是第一個非空白符開始。
parseInt('  \n\r\f\t\v   11', 2) // 3呢袱,相當于 parseInt('11', 2)
  1. string 參數(shù)的「第一個非空格字符」不能轉(zhuǎn)換為數(shù)字官扣,或者當 radix < 2 || radix > 36 時,返回值為 NaN产捞。
parseInt('a11') // NaN
parseInt('11', 1) // NaN
parseInt('11', 37) // NaN

但請注意醇锚,并不是所有的字母開頭的都返回 NaN。比如 parseInt('a11', 12) 返回值為 1453坯临。因為超過十進制之后焊唬,字母也可能用于表示相應(yīng)的進制數(shù)的。

  1. radix 參數(shù)為 undefined看靠、null赶促、0 或缺省(未顯式指定)時挟炬,JavaScript 引擎會假定以下情況:

    1. 如果 string 是以 0x0X 開頭的鸥滨,那么 radix 將會假定為 16,將其余部分當作十六進制數(shù)去解析谤祖。比如 parseInt('0xf') 相當于 parseInt('f', 16)婿滓,結(jié)果為 15
    2. 如果 string 是以 0 開頭的粥喜,那么 radix 在不同的環(huán)境下凸主,有可能被假定為 8(八進制)或假定為 10(十進制)。具體選擇哪一種作為 radix 的值额湘,視乎運行 JavaScript 的宿主環(huán)境(前面提到過了)卿吐。因此,在使用 parseInt 時锋华,一定要顯式指定 radix 參數(shù)嗡官。
    3. 如何 string 是以任何其他值開頭,radix 會被假定為 10(十進制)毯焕。
  2. parseIntstring 的解析規(guī)則是:從第一個非空白符開始衍腥,然后一直往后面查找,若有任意一個字符不能被轉(zhuǎn)換為數(shù)值就會停止纳猫,那么最終被解析的字符串就是從開始到停止的這一截字符串紧阔。

parseInt('11a', 10) // 結(jié)果為 11,被解析的字符串為 '11'
parseInt('11a', 11) // 結(jié)果為 142续担,被解析的字符串為 '11a',因為在十一進制里面活孩,a 是有意義的物遇。

所以,在使用 parseInt 處理 BigInt 類型的時候,最終的返回值總是為 Number 類型(過程中會失去精度)询兴,其中 BigInt 類型的拖尾的 n 是會被丟棄的乃沙。

parseInt(1024n, 10) // 1024
parseInt(1024n, 36) // 46732,相當于 parseInt('1024', 36)

// 注意诗舰,有別于以下這個
parseInt('1024n', 36) // 1682375

原因非常的簡單警儒,前面也提到過的。當 parseInt 的第一個參數(shù)不是 String 類型時眶根,會調(diào)用 BigInt.prototype.toString() 方法先轉(zhuǎn)換為字符串蜀铲,即 1024n.toString(),結(jié)果為 1024属百。

四记劝、結(jié)尾

回到文章開頭的題目:

[
  parseInt('1', 0),
  parseInt('2', 1),
  parseInt('3', 2)
]

這時候,是不是就可以快速說出答案了:[1, NaN, NaN]族扰。

借機徹底弄懂了 parseInt() 的方法厌丑,可以滿意地離開了,The end.

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末渔呵,一起剝皮案震驚了整個濱河市怒竿,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌扩氢,老刑警劉巖耕驰,帶你破解...
    沈念sama閱讀 219,188評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異类茂,居然都是意外死亡耍属,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,464評論 3 395
  • 文/潘曉璐 我一進店門巩检,熙熙樓的掌柜王于貴愁眉苦臉地迎上來厚骗,“玉大人,你說我怎么就攤上這事兢哭×旖ⅲ” “怎么了?”我有些...
    開封第一講書人閱讀 165,562評論 0 356
  • 文/不壞的土叔 我叫張陵迟螺,是天一觀的道長冲秽。 經(jīng)常有香客問我,道長矩父,這世上最難降的妖魔是什么锉桑? 我笑而不...
    開封第一講書人閱讀 58,893評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮窍株,結(jié)果婚禮上民轴,老公的妹妹穿的比我還像新娘攻柠。我一直安慰自己,他們只是感情好后裸,可當我...
    茶點故事閱讀 67,917評論 6 392
  • 文/花漫 我一把揭開白布瑰钮。 她就那樣靜靜地躺著,像睡著了一般微驶。 火紅的嫁衣襯著肌膚如雪浪谴。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,708評論 1 305
  • 那天因苹,我揣著相機與錄音苟耻,去河邊找鬼。 笑死容燕,一個胖子當著我的面吹牛梁呈,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播蘸秘,決...
    沈念sama閱讀 40,430評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼官卡,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了醋虏?” 一聲冷哼從身側(cè)響起寻咒,我...
    開封第一講書人閱讀 39,342評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎颈嚼,沒想到半個月后毛秘,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,801評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡阻课,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,976評論 3 337
  • 正文 我和宋清朗相戀三年叫挟,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片限煞。...
    茶點故事閱讀 40,115評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡抹恳,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出署驻,到底是詐尸還是另有隱情奋献,我是刑警寧澤,帶...
    沈念sama閱讀 35,804評論 5 346
  • 正文 年R本政府宣布旺上,位于F島的核電站瓶蚂,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏宣吱。R本人自食惡果不足惜窃这,卻給世界環(huán)境...
    茶點故事閱讀 41,458評論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望征候。 院中可真熱鬧钦听,春花似錦洒试、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,008評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽卒煞。三九已至痪宰,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間畔裕,已是汗流浹背衣撬。 一陣腳步聲響...
    開封第一講書人閱讀 33,135評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留扮饶,地道東北人具练。 一個月前我還...
    沈念sama閱讀 48,365評論 3 373
  • 正文 我出身青樓,卻偏偏與公主長得像甜无,于是被迫代替她去往敵國和親扛点。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 45,055評論 2 355

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