《原神攻略》可莉適配武器分析
0x01 變數提升
JavaScript 引擎的工作方式是,先解析程式碼,獲取所有被宣告的變數,然後再一行一行地執行。這造成的結果,就是所有的變數的宣告語句,都會被提升到程式碼的頭部,這就叫做變數提升(hoisting)。
console.log(a);
var a = 1;
上面程式碼首先使用console.log方法,在控制檯(console)顯示變數a的值。這時變數a還沒有宣告和賦值,所以這是一種錯誤的做法,但是實際上不會報錯。因為存在變數提升,真正執行的是下面的程式碼。
var a;
console.log(a);
a = 1;
最後的結果是顯示undefined,表示變數a已宣告,但還未賦值。
0x02 為什麼有些人常量寫在運算子左邊
var x = 1;
var y = 2;
if (x = y) {
console.log(x);
}
// "2"
上面程式碼的原意是,當x等於y的時候,才執行相關語句。但是,不小心將嚴格相等運算子寫成賦值表示式,結果變成了將y賦值給變數x,再判斷變數x的值(等於2)的布林值(結果為true)。
這種錯誤可以正常生成一個布林值,因而不會報錯。為了避免這種情況,有些開發者習慣將常量寫在運算子的左邊,這樣的話,一旦不小心將相等運算子寫成賦值運算子,就會報錯,因為常量不能被賦值。
if (x = 2) { // 不報錯
if (2 = x) { // 報錯
0x03 object(物件)
物件是最複雜的資料型別,又可以分成三個子型別。
- 狹義的物件(object)
- 陣列(array)
- 函式(function)
狹義的物件和陣列是兩種不同的資料組合方式。函式其實是處理資料的方法,JavaScript 把它當成一種資料型別,可以賦值給變數,這為程式設計帶來了很大的靈活性,也為 JavaScript 的“函數語言程式設計”奠定了基礎。
引用
引用只侷限於物件,如果兩個變數指向同一個原始型別的值。那麼,變數這時都是值的拷貝。
0x04 number
整數和浮點數
JavaScript 內部,所有數字都是以64位浮點數形式儲存,即使整數也是如此。所以,1與1.0是相同的,是同一個數。
1 === 1.0 // true
這就是說,JavaScript 語言的底層根本沒有整數,所有數字都是小數(64位浮點數)。容易造成混淆的是,某些運算只有整數才能完成,此時 JavaScript 會自動把64位浮點數,轉成32位整數,然後再進行運算
由於浮點數不是精確的值,所以涉及小數的比較和運算要特別小心。
0.1 + 0.2 === 0.3
// false
0.3 / 0.1
// 2.9999999999999996
(0.3 - 0.2) === (0.2 - 0.1)
// false
正0和負0
幾乎所有場合,正零和負零都會被當作正常的0。
唯一有區別的場合是,+0或-0當作分母,返回的值是不相等的。
(1 / +0) === (1 / -0) // false
上面的程式碼之所以出現這樣結果,是因為除以正零得到+Infinity,除以負零得到-Infinity,這兩者是不相等的(關於Infinity詳見下文)。
NaN
NaN是 JavaScript 的特殊值,表示“非數字”(Not a Number),主要出現在將字串解析成數字出錯的場合。
需要注意的是,NaN不是獨立的資料型別,而是一個特殊數值,它的資料型別依然屬於Number,使用typeof運算子可以看得很清楚。
Infinity
Infinity表示“無窮”,用來表示兩種場景。一種是一個正的數值太大,或一個負的數值太小,無法表示;另一種是非0數值除以0,得到Infinity。
// 場景一
Math.pow(2, 1024)
// Infinity
// 場景二
0 / 0 // NaN
1 / 0 // Infinity
上面程式碼中,第一個場景是一個表示式的計算結果太大,超出了能夠表示的範圍,因此返回Infinity。第二個場景是0除以0會得到NaN,而非0數值除以0,會返回Infinity。
Infinity有正負之分,Infinity表示正的無窮,-Infinity表示負的無窮。
Infinity === -Infinity // false
1 / -0 // -Infinity
-1 / -0 // Infinity
上面程式碼中,非零正數除以-0,會得到-Infinity,負數除以-0,會得到Infinity。
由於數值正向溢位(overflow)、負向溢位(underflow)和被0除,JavaScript 都不報錯,所以單純的數學運算幾乎沒有可能丟擲錯誤。
Infinity大於一切數值(除了NaN),-Infinity小於一切數值(除了NaN)。
Infinity > 1000 // true
-Infinity < -1000 // true
Infinity與NaN比較,總是返回false。
Infinity > NaN // false
-Infinity > NaN // false
Infinity < NaN // false
-Infinity < NaN // false