年關將近,金三銀四跳槽季要來了,開始整理面試題前端
基本類型有七種面試
null
undefined
boolean
number
string
symbol
(較新標準)BigInt
(新標準)NaN
也屬於 number
類型,而且 NaN
不等於自身數組
棧內存
中的簡單數據段不可變的
Array.prototype.sort.call('abc');
(會報錯)__proto__
沒有屬性
基本包裝類型
訪問的屬性/方法// 經過包裝類型訪問基礎類型特性
let str = 'abc';
console.log(str.length)
// 當你調用 `str.length` 時,實際過程是這樣的:
// -> 建立String類型的一個實例
// -> 在實例上調用指定的方法
// -> 銷燬這個實例
let _str = new String(str);
let len = _str.length;
_str = null;
複製代碼
typeof
,可是 typeof null === 'object'
null
是基礎類型,不是 Objecttypeof
檢測null會產生BUG// 借鑑 Vue 源碼的 object 檢測方法
function isObject (obj: any): Boolean {
return obj !== null && typeof obj === 'object'
}
複製代碼
Object.prototype.toString.call
(萬能方法)
[[class]]
[object type]
// 借鑑 Vue 源碼的檢測方法
let _toString = Object.prototype.toString;
function toRawType (value: any): String {
// 獲取 從第九個到倒數第二個 字符
// 好比 [object String] 獲取 String
return _toString.call(value).slice(8, -1)
}
複製代碼
valueOf
,而後調用 toString
。(這兩個方法能夠被重寫)+
其餘操做都會以數字進行計算,若是是 +
運算,若是不是全部字面量都是number
(都是number就是數字的加法咯),那麼會轉換爲字符串(toString
)進行拼接遵循IEEE 754 雙精度版本(64位)
標準的語言都有的問題。計算機沒法識別十進制,JS會將十進制轉換爲對應的二進制(二進制即:0
和 1
)。bash
那麼 怎麼用 0
和 1
來表示 0.1
和 0.2
呢?微信
console.log(0.1.toString(2));
// -> 0.0001100110011001100110011001100110011001100110011001101
console.log(0.2.toString(2));
// -> 0.001100110011001100110011001100110011001100110011001101
複製代碼
這樣看似沒問題啊。爲何會有BUG呢?函數
別忘了:JS的精確度區間 約爲正負 2^53
,超出限制會截斷。因此你看到的 0.1 不是真的 0.1。ui
先乘再除
BigInt
(兼容性不好)JS中除了 "假" 值之外就是 "真" 值。this
"假"值包括 7 個spa
undefined
null
false
NaN
''
0
-0
在條件判斷的隱式轉換中:"假" 值會轉換爲 false
,"真" 值會轉換爲 true
;prototype
兩個空間
堆
上,儲存引用類型自己的數據(固然數據量會比較大)棧
上,儲存對堆
上數據的引用(存儲堆上的內存地址,也就是指針)let a={}; a.x=1;
Object.prototype.toString.call
檢測 [[class]]
instanceof
判斷引用類型constructor
判斷引用類型(constructor
是可寫的,慎用)instanceof
內部機制是經過判斷對象的原型鏈中是否是能找到對應的的prototype
因此在驗證iframe時會有BUG,由於 window.Array.prototype !== window.frames[0].Array.prototype
,因此不存在繼承關係
// 實現 instanceof
function instanceof(obj, target) {
// 得到對象的原型
obj = obj.__proto__
// 判斷對象的類型是否等於類型的原型
while (true) {
// 若是__proto__ === null 說明原型鏈遍歷完畢
if (obj === null) {
return false
}
// 若是存在 obj.__proto__ === target.prototype
// 說明對象是該類型的實例
if (obj === target.prototype) {
return true
}
// 原型鏈上查找
obj = obj.__proto__
}
}
複製代碼
會返回 false
由於基礎類型沒有 __proto__
let str = '123';
console.log(str instanceof String) // -> false
複製代碼
可是若是更改了 靜態方法Symbol.hasInstance
就能夠判斷了
class StringType {
static [Symbol.hasInstance](val) {
return typeof val === 'string'
}
}
console.log(str instanceof StringType) // -> true
複製代碼
數組是一種類列表對象,其數據在內存中也能夠不連續
數組應該是一段線性分配的內存,可是JS的Array的檢索和更新方式和對象如出一轍
Array.prototype
,向上再繼承自Object.prototype
let obj = {
'2': 3,
'3': 4,
'length': 2,
'splice': Array.prototype.splice,
'push': Array.prototype.push
}
obj.push(1)
obj.push(2)
console.log(obj);
// Object(4) [empty × 2, 1, 2, splice: ƒ, push: ƒ]
複製代碼
delete arr[2]
,並不能減小length,而只是刪除了對應的屬性(變成empty)Array.isArray()
會返回 false
Array.from
能夠轉換爲數組常常碰見的類數組
arguments
...args
代替,這樣不定參數就是真數組PS: 感謝 @沉末_ 的補充
類型轉換都是先 valueOf
再 toString
;
右邊
!
優先級比 ==
高,先執行 !
![]
獲得 falsefalse
轉化爲數字 0
左邊
[].valueOf()
原始值 仍是 []''
轉化爲數字 0
因此:0 == 0
,答案是 true
驗證:
let arr1 = [];
let arr2 = [];
console.log(arr1 == !arr2) // -> true
arr1.toString = () => {
console.log(111)
return 1
}
console.log(arr1 == !arr2)
// -> 111
// -> false
複製代碼
===
不進行隱式轉換==
會進行隱式轉換
{a: 1} == "[object Object]"
左邊會執行 .toString()
依然是類型轉換邏輯:基礎類型經過 valueOf
進行隱式轉換
更改 valueOf
方法就能夠實現
let a = {
value: 0,
valueOf: function() {
this.value++;
return this.value;
}
};
console.log(a == 1 && a == 2);
複製代碼
Object.is
和 === 的區別 ?Object.is(v1, v2)
修復了 ===
的一些BUG (-0和+0, NaN和NaN)
:
// === 案例
-0 === +0 // -> true
NaN !== NaN // -> false
Object.is(-0, +0) // -> false
Object.is(NaN, NaN) // -> true
複製代碼