1.JavaScript規(guī)定了幾種語(yǔ)言類型?
6種類型如下:
3種基本類型:string、number、boolean
1種引用類型:Object
2種特殊類型:null、undefined
ES6新增類型:Symbol
每個(gè)從Symbol()返回的symbol值都是唯一的;
一個(gè)symbol值能作為對(duì)象屬性的標(biāo)識(shí)符,這是該數(shù)據(jù)類型僅有的目的;
2.JavaScript對(duì)象的底層數(shù)據(jù)結(jié)構(gòu)是什么?
簡(jiǎn)單概括包括幾個(gè)部分:
1.Fixed Array:包含對(duì)象屬性key和value按照順序存儲(chǔ)
2.Map建立Fixed Array中key和value的索引和查找方式
3.Cache策略(Hash)緩存被訪問過的屬性number值(內(nèi)存偏移量)
# 從Chrome源碼看JS Object的實(shí)現(xiàn)(更新)
3.Symbol類型在實(shí)際開發(fā)中的應(yīng)用、可手動(dòng)實(shí)現(xiàn)一個(gè)簡(jiǎn)單的Symbol?
Symbol是由ES6規(guī)范引入的一項(xiàng)新特性,它的功能類似于一種標(biāo)識(shí)唯一性的ID。通常情況下,我們可以通過調(diào)用Symbol()函數(shù)來(lái)創(chuàng)建一個(gè)Symbol實(shí)例,實(shí)際開發(fā)應(yīng)用包括:
- 作為屬性名
- 代替常量
- 定義私有屬性或方法
- 創(chuàng)建全局唯一的標(biāo)識(shí)
# 理解和使用ES6中的Symbol
# ES6 系列之模擬實(shí)現(xiàn) Symbol 類型
4.JavaScript中的變量在內(nèi)存中的具體存儲(chǔ)形式?
4.1 基本數(shù)據(jù)類型:
基本數(shù)據(jù)類型值指保存在棧內(nèi)存中的簡(jiǎn)單數(shù)據(jù)段。訪問方式是按值訪問;
4.2 引用數(shù)據(jù)類型:
引用數(shù)據(jù)類型值指保存在堆內(nèi)存中的對(duì)象。也就是,變量中保存的實(shí)際上的只是一個(gè)指針,這個(gè)指針指向內(nèi)存中的另一個(gè)位置,該位置保存著對(duì)象。訪問方式是按引用訪問。
4.3 堆&棧:
兩者都是存放臨時(shí)數(shù)據(jù)的地方。
棧是先進(jìn)后出的,就像一個(gè)桶,后進(jìn)去的先出來(lái),它下面本來(lái)有的東西要等其他出來(lái)之后才能出來(lái)。
堆是在程序運(yùn)行時(shí),而不是在程序編譯時(shí),申請(qǐng)某個(gè)大小的內(nèi)存空間。即動(dòng)態(tài)分配內(nèi)存,對(duì)其訪問和對(duì)一般內(nèi)存的訪問沒有區(qū)別。對(duì)于堆,我們可以隨心所欲的進(jìn)行增加變量和刪除變量,不用遵循次序。
棧區(qū)(stack) 由編譯器自動(dòng)分配釋放 ,存放函數(shù)的參數(shù)值,局部變量的值等。
堆區(qū)(heap) 一般由程序員分配釋放,若程序員不釋放,程序結(jié)束時(shí)可能由OS回收。
堆(數(shù)據(jù)結(jié)構(gòu)):堆可以被看成是一棵樹,如:堆排序;
棧(數(shù)據(jù)結(jié)構(gòu)):一種先進(jìn)后出的數(shù)據(jù)結(jié)構(gòu)。
# 基本數(shù)據(jù)類型和引用數(shù)據(jù)類型判斷&存儲(chǔ)訪問&類型轉(zhuǎn)換
5.基本類型對(duì)應(yīng)的內(nèi)置對(duì)象,以及他們之間的裝箱拆箱操作?
5.1 裝箱
// 顯式
var num = new Number(1);
var flag = new Boolean(false);
var str = new String('str');
// 隱式
var num = 123;
num.toFixed(2); // "123.00"
5.2 拆箱
拆箱調(diào)用ToPrimitive,默認(rèn)情況下先調(diào)用valueOf在調(diào)用toString,String情況較為特殊會(huì)先調(diào)用toString再調(diào)用valueOf
var obj = {
valueOf : () => {console.log("valueOf"); return []},
toString : () => {console.log("toString"); return []}
}
String(obj)
// toString
// valueOf
// Uncaught TypeError: Cannot convert object to primitive value
obj+' '
//valueOf
//toString
// Uncaught TypeError: Cannot convert object to primitive value
Number(obj)
//valueOf
//toString
// Uncaught TypeError: Cannot convert object to primitive value
6.理解值類型和引用類型?
6.1值類型:
- 占用空間固定,函數(shù)運(yùn)行時(shí)保存在棧中;
- 保存與復(fù)制的是值本身;
- 可以使用 typeOf()檢測(cè)值的類型(除了null);
- 基本類型數(shù)據(jù)是值類型;
6.2 引用類型:
- 占用空間不固定,保存在堆中,函數(shù)運(yùn)行時(shí)棧中只保存引用;
- 保存與復(fù)制的是指向?qū)ο蟮囊粋€(gè)指針;
- 需要使用 instanceof() 檢測(cè)數(shù)據(jù)類型;
- 使用 new() 方法構(gòu)造出的對(duì)象是引用型;
7.null和undefined的區(qū)別?
| 名稱 | 含義 | typeof結(jié)果 | 判等操作 | 其他 |
|---|---|---|---|---|
| null | 表示一個(gè)特殊值,即"空值" | object (可以認(rèn)為null是特殊對(duì)象,是null自有類型唯一成員) | ==認(rèn)為二者相等,表示值的空缺 | null表示程序級(jí)別、意料之中的空缺 |
| undefined | 表示值得空缺 | undefined | ===操作符區(qū)分二者 | undefined表示系統(tǒng)級(jí)、出乎意料的類似錯(cuò)誤的值得空缺 |
8.至少可以說出三種判斷JavaScript數(shù)據(jù)類型的方式,以及他們的優(yōu)缺點(diǎn),如何準(zhǔn)確的判斷數(shù)組類型?
| 名稱 | 使用場(chǎng)景 | 缺點(diǎn) | 其他 |
|---|---|---|---|
| typeof | 判斷基本類型(除了null) | 無(wú)法判斷引用類型(都是object) | |
| instanceof | 判斷實(shí)例是否在原型鏈上有關(guān)系 | 無(wú)法判斷未包裝的基本類型 | 無(wú)法跨iframe判斷 |
| constructor | 能夠判斷大部分情況下數(shù)據(jù)類型 | 判斷null和undefined報(bào)錯(cuò)、constructor有時(shí)會(huì)被修改 | 無(wú)法跨iframe判斷 |
| toString | Object.prototype.toString()可以方便判斷類型 | 自定義類沒有重載toString方法時(shí)判斷有問題 |
準(zhǔn)確判斷數(shù)組:Array.isArray()
其他方法判斷:constructor|toString|instanceof
判斷js數(shù)據(jù)類型的四種方法,以及各自的優(yōu)缺點(diǎn)
9.可能發(fā)生隱式類型轉(zhuǎn)換的場(chǎng)景以及轉(zhuǎn)換原則,應(yīng)如何避免或巧妙應(yīng)用?
9.1 if語(yǔ)句等隱式轉(zhuǎn)boolean情況:
| 數(shù)值類型 | 轉(zhuǎn)換為true的值 | 轉(zhuǎn)換為false的值 |
|---|---|---|
| String | 非空字符串 | ""(空串) |
| Number | 任何非零數(shù)字 | 0和NaN |
| Object | 任何對(duì)象 | null |
| Undefined | N/A | undefined |
9.2 == 隱式轉(zhuǎn)換情況:
數(shù)據(jù)類型不同時(shí),遵循以下原則:
1.如果一個(gè)操作數(shù)是布爾值,比較之前將其轉(zhuǎn)化為數(shù)值(false-0、true-1)
2.一個(gè)是字符串一個(gè)是數(shù)值,比較前將字符串轉(zhuǎn)為數(shù)值
3.如果一個(gè)是對(duì)象一個(gè)不是,則調(diào)用對(duì)象ValueOf方法再根據(jù)前面規(guī)則比較
其他比較時(shí):
1.null==undefined
2.NaN!=NaN
3.兩個(gè)對(duì)象比較時(shí),比較是不是同一個(gè)對(duì)象
9.3 運(yùn)算符隱式轉(zhuǎn)換情況:
+運(yùn)算符:數(shù)字和字符串相加會(huì)將數(shù)字轉(zhuǎn)為字符串后進(jìn)行拼接,一位運(yùn)算符+會(huì)將字符串轉(zhuǎn)為數(shù)字
其他運(yùn)算符:將操作數(shù)轉(zhuǎn)換為數(shù)字后運(yùn)算
10.出現(xiàn)小數(shù)精度丟失的原因,JavaScript可以存儲(chǔ)的最大數(shù)字、最大安全數(shù)字,JavaScript處理大數(shù)字的方法、避免精度丟失的方法?
精度丟失原因:
JavaScript使用了IEEE 754規(guī)范,二進(jìn)制儲(chǔ)存十進(jìn)制的小數(shù)時(shí)不能完整的表示小數(shù)
// exp: 0.1 + 0.2 !== 0.3
最大數(shù)字: Number.MAX_VALUE = 1.7976931348623157e+308
最大安全數(shù)字: Number.MAX_SAFE_INTEGER=9007199254740991
避免精度丟失:
計(jì)算小數(shù)時(shí),先乘100或1000,變成整數(shù)再運(yùn)算
使用大整數(shù),有一個(gè)最新提案,BigInt大整數(shù),它可以表示任意大小的整數(shù),注意只能表示整數(shù),而不受安全整數(shù)的限制