來源:JavaScript 型別篇 - JS 面試常見核心知識
console.log(typeof Number('1'));
const number = 1;
console.log(typeof number.toString());
原形方法可以透過 new Number()
展開 prototype 來查看,其他原始型別也是使用同樣的方式。
console.log(+ '1');
console.log(+ true);
console.log(- true);
!
表示 not
console.log(!0); // true
console.log(!1); // false
console.log(!!1); // true
總結:前後運算元其中一個是字串或物件型別,+ 視為字串運算子。
console.log(1 + 1);
console.log('這是' + '一句話');
console.log(1 + true);
// 2
// '這是一句話'
// 2
console.log(1 + '這是一句話');
console.log(true + true);
// '1這是一句話'
// 2
物件型別會被套用 String() 轉型
String({})
➡️ '[object Object]'
String([])
➡️ ''
console.log(1 + {});
console.log([1]);
console.log(1 + [1]);
console.log(1 + [1, 2]);
// 1[object Object]
// '1'
// '11'
// '11,2'
console.log(1n + 3n);
console.log(100n * 100n);
console.log(1 + 1n);
// 4n
// 10000n
// 報錯:uncaught typeError:
// - cannot mix BigInt and other types, use explicit conversions
console.log(typeof Symbol(1));
console.log(Symbol(1) + 1); // 規則三
console.log(Symbol(1) + true); // 規則三
console.log(Symbol(1) + null); // 規則三
console.log(Symbol(1) + 1n); // 規則三
// Uncaught TypeError: Cannot convert a Symbol value to a number
console.log(Symbol(1) + {}); // 規則二
// Uncaught TypeError: Cannot convert a Symbol value to a string
console.log(Symbol(1) + '123'); // 規則一
// Uncaught TypeError: Cannot convert a Symbol value to a string
console.log(NaN === NaN);
// false
物件型別相比會是 false。因為當使用 ===
進行比較時,將檢查這兩個物件是否具有相同的參考(是否指向內存中的同一位置)。
以[] === []
為例,每個空陣列字面量 []
都會創建一個全新的陣列物件,分別存在記憶體中的不同位置,具有不同的參考。所以就算這兩個陣列在結構上(即內容和順序)完全相同,它們也是兩個獨立的物件。[] === []
實際上是在比較兩個指向不同記憶體位置的參考,因為它們的參考不同,結果為 false
。
console.log({} === {});
console.log([] === []);
console.log(new Number(1) === new Number(1));
// false
// false
// false
console.log(+0 === -0);
// true
==
在比較兩個值之前,會先強制轉換型別與值。
比對表:https://dorey.github.io/JavaScript-Equality-Table/
這三者進行比較時,都使用 Number 來轉型。
console.log(1 == true);
console.log(3 == true);
// true
// false,因為 true 轉型後 Number(true) 會是 1
不轉型,跟其他值相比都是 false,但 null 和 undefined 相比會是 true
console.log(null == undefined);
// true
console.log(null == 0);
console.log(undefined == 0);
console.log(undefined == '');
// false
// false
// false
轉型為 「數學值」,沒有 NaN、沒有小數點、沒有最大值
其他概念和 Number 接近
console.log(1 == 1n);
console.log(1 === 1n);
console.log(9007199254740991 == 9007199254740991n);
console.log(9007199254740993 == 9007199254740993n); // 超出最大安全數,不精準
// true
// false
// true
// false
物件和其他型別比較,會透過「包裹物件」來把物件轉成相同的型別
例外:
console.log({} == 'object Object');
console.log({} == 1);
console.log({} == '1234');
console.log([1] == true);
// true
// false
// false
// true
console.log([] == 0);
// 先 toString 再套用 Number,[] 會變成 0
// true
console.log([1] == 1);
// true
console.log([1, 2] == 12);
// 先 toString 再套用 Number,[1, 2] 會變成 NaN
// false
Object.is
同值比較比較任意兩個值是不是相等。
console.log(Object.is(1, 1));
console.log(Object.is(1, "1"));
// true
// false
NaN/NaN 和 +0/-0 的比較問題,可以透過 Object.is
來分辨。另外,分辨 NaN
也可以使用 Number.isNaN
。
console.log(Object.is(+0, -0));
console.log(Object.is(NaN, NaN));
// false
// true
console.log(Number.isNaN(NaN));
console.log(Number.isNaN('NaN'));
// true
// false,Number.isNaN 不會將 字串 NaN 視為NaN