犀牛書第三章主要講了類型、值還有變量,本篇主要講 數據類型。es6
須要注意引用類型和非引用類型的區別、-0、NaN、八進制、字符串編碼等問題。編程
類型轉換部分查看:數組
0.1 + 0.2 === 0.3;
複製代碼
var e = '👋';
console.log(e.length);
複製代碼
0 === -0;
1/0 === 1/-0;
複製代碼
數據類型主要分爲兩類:瀏覽器
JavaScript 會在 程序期待使用對應數據類型 的地方 自動進行類型轉換(常說的 隱式類型轉換,如將非 Boolean 型的數據放在 if 判斷條件中、使用非字符串和數字進行 + 運算等)。安全
JavaScript 變量是 無類型的,變量 能夠賦予任何類型的值,而且 能夠從新賦予不一樣類型的值(也就是第一章所說的 弱類型 概念)。閉包
JavaScript 採用 詞法做用域(也稱 靜態做用域,正是由於詞法做用域的緣故,纔會出現閉包,在變量定義的時候,它的做用域就已經肯定好了)。編程語言
JavaScript 中的數字採用 IEEE 754 標準,整數範圍爲 -(2**53) ~ 2**53
(Number.MAX_SAFE_INTEGER
的值爲 2**53 - 1
,和這裏相差了 1,由於 超出(安全)範圍的值沒法保證精度,故而最大值自己是不安全的,可能由某個失去精度的值轉換而來️)。函數
下面是 MDN 中的例子。post
var x = Number.MAX_SAFE_INTEGER + 1;
var y = Number.MAX_SAFE_INTEGER + 2;
// 9007199254740991 9007199254740992 9007199254740992
console.log(Number.MAX_SAFE_INTEGER, x, y);
// true
console.log(x === y);
複製代碼
JavaScript 中的實際操做如數組索引等 是基於 32 位整數 的。學習
// 4294967296
console.log(2**32);
// 安全
new Array(2**32 - 1);
// 報錯:RangeError: Invalid array length
new Array(2**32);
複製代碼
NaN 的意思是 Not a Number,不過 typeof NaN 是 number,因此它是一個不是(有效)數字的數字值。
因爲 NaN 不等於任何值包括自身,可使用 a !== a 來判斷 a 是否是一個 NaN 值。
八進制雖然大部分瀏覽器支持,可是它自己是 非標準的,在嚴格模式下 明令禁止(八進制使用 0 做爲前置標識,這會在某些地方引發歧義)。
// 9
console.log(09);
// 15
console.log(017);
// 上述都是前導 0 可是卻按照兩種進制去進行了解析
(function() {
'use strict';
// 嚴格模式下會報錯:SyntaxError: Octal literals are not allowed in strict mode.
console.log(09);
console.log(017);
})();
複製代碼
JavaScript 中的浮點數計算精度問題是因爲採用了 IEEE 754 浮點數表示法(大部分編程語言都是採用這個標準,因此這個問題真不是 JavaScript 的設計缺陷之類的),二進制表示法 致使十進制的小數沒法精確的標識,因此致使一系列浮點計算的精度問題。
var a = 0.3 - 0.2;
var b = 0.2 - 0.1;
// false
console.log(a === b);
// 0.09999999999999998 0.1
console.log(a, b);
複製代碼
這種時候建議使用整數來進行計算:
var a = (0.3 * 10 - 0.2 * 10) / 10;
var b = (0.2 * 10 - 0.1 * 10) / 10;
// true
console.log(a === b);
// 0.1 0.1
console.log(a, b);
複製代碼
0 和 -0 並不徹底對等。
var a = 0, b = -0;
// 全等號會認爲他們相等
console.log(a === b);
// 可是進行除法計算時將會影響計算結果
// Infinity -Infinity false
console.log(1/a, 1/b, 1/a === 1/b);
複製代碼
JavaScript 字符串是由無符號的 16 位值 組成的序列,常見的 Unicode 字符都是經過 16 位內碼錶示的,若是出現 超出範圍 的字符,將會遵循 UTF-16 編碼規則,使用 兩個 16 位值 標識,然而 JavaScript 中對字符串的操做都是 基於 16 位值。
// 👋 遵循 UTF-16 規則,實際編碼爲 '\ud83d\udc4b',在 JavaScript 中佔用兩個字符長度
var e = '👋';
// 2 d83d dc4b
console.log(e.length, e.charCodeAt(0).toString(16), e.charCodeAt(1).toString(16));
// true 👋 👋
console.log(e === '\ud83d\udc4b', e, '\ud83d\udc4b');
複製代碼
從語義上,null 表明 空值,undefined 表明 未定義、不存在,正常而言 null 可用來給變量賦值(清空變量等),而 不多使用 undefined 去給變量賦值。
聲明全局變量時變量會 成爲全局對象的一個屬性。
// 定義全局變量時 a 會直接掛載到 全局對象下
var a = {};
// {} {} true
console.log(a, window.a, a === window.a);
複製代碼