8 天重新認識 JS Day 01

紀錄閱讀 “8 天重新認識 JS” Day 01,記錄不太熟的基本知識


變數宣告

  • 宣告變數可以不打 var 將被視為全域變數使用(覆蓋)
1
2
3
4
a = 1
b = 2
b = 3
console.log(a,b)

如果在全域作用宣告a與b在這個情況下,a與b被視為全域變數被宣告

  • 當使用 var 宣告時,變數可以被重新宣告
1
2
var a = 1
var b = 2

資料型別

  • 宣告字串使用"'都可以,但要使用單引號包裹可以使用跳脫字元\
1
let a = 'Let\'s GO'

數字

Number 特殊形態

數字除了常規整數和浮點數,還包含三種特殊數字型態

Infinity-InfinityNaN

  • 正整數/0 會得到 Infinity
  • 任何負數/0 會得到 -Infinity
  • 0/0、Infinity/Infinity、-Infinity/-Infinity 會得到 NaN
  • typeof NaN 會得到 number
  • NaN === NaN 會得到 false

通常使用isNaN(value)來判斷輸入值否為 NaN

0.1 + 0.2 === 0.3 (false)

這是由於在程式世界中計算會將 0.1 轉為二進位時沒辦法完美轉換,只能用無限循環的位數來趨近於十進位的小數
有點像是 Pi 那種無限小數的感覺,導致計算後的 0.3 會有小數變成 0.30000004 ,而得到 false

解決方式有兩種

  • 使用 Number.EPSILON 來判斷
1
2
// 先使用Math.abs將小數調整為整數在判斷
console.log(Math.abs(0.1 + 0.2 - 0.3) <= Number.EPSILON) //true

ES6 提供了 Number.EPSILON 最小精度來幫助我們判斷,如果一個數值的誤差小於這個值,那我們就可以認為幾乎沒有誤差了

null、undefined

  • typeof null === ‘object’ 是陳年 BUG

  • undefined 在非全域作用域下可以作為變數使用

1
2
3
4
5
6
(
function(){
var undefined = '87';
console.log(undefined, typeof undefined) //'87', 'string'
}
)()

也可以做為參數使用

1
2
3
4
5
(
function(undefined){
console.log(undefined, typeof undefined) //'87', 'string'
}
)('87')

物件

判斷屬性使否在物件中存在

  1. 直接存取

但遇到值是undefined這招就沒用

1
2
var obj = {};
console.log(obj.name); //undefined
  1. 使用 inhasOwnProperty() 檢查
1
2
3
4
5
6
7
8
var obj = {
name:'abc'
}
console.log('name' in obj) //true
console.log('val' in obj) //false

obj.hasOwnProperty('name') //true
obj.hasOwnProperty('val') //false

使用 hasOwnProperty() 不會往上檢查物件原型鍊(prototype chain),只會檢查物件本身是否存在這個屬性
in 運算子會繼續順著物件原型鍊上做檢查

1
2
obj.hasOwnProperty('hasOwnProperty') //false
console.log('hasOwnProperty' in obj) //true

陣列

  • 陣列長度(length)是可以被覆寫的
1
2
3
4
5
6
7
8
var a = ["apple", "bear", "cat"]
a.length; //3

a.length = 1
console.log(a) //["apple"]

a.length = 3
console.log(a) //["apple", undefined, undefined]

四則運算

加法

1
2
3
Infinity + Infinity //Infinity
-Infinity + -Infinity //-Infinity
-Infinity + Infinity //NaN

當遇到字串與 number、boolean、object 相加時,會呼叫其原型方法.toString()轉型後,再進行字串拼接

nullundefined 則透過 JS 的 String() 方法來轉為字串 “null”、”undefined”

1
2
3
4
5
6
7
8
9
10
11
12
13
10 + 'abc' //'10abc'
true + '888' //'true888'
100 + {} //'100[object Object]'

// 數字與 undefined 相加時,undefined 會被嘗試轉為數字,也就是 NaN

123 + undefined //NaN
"abc" + undefined // "abcundefined"

// 當數字與 null 相加時,null 會被嘗試轉為數字,也就是0

123 + null //123
"123" + null //"123null"

減法

1
2
3
4
Infinity - Infinity //NaN
-Infinity - -Infinity //NaN
-Infinity - Infinity //-Infinity
Infinity - -Infinity //Infinity

一般型態

如果 string、boolean、undefined、null 在做減法運算時,若其中一方屬性不是數字,JS 會在背後透過 Number() 嘗試轉型為數字後在進行計算。

1
2
3
4
5
6
7
8
9
100 - '50' //50
100 - 'abc' //NaN
// false 經過 Number() 轉型會變成 0
100 - false //0
// true 經過 Number() 轉型會變成 1
100 - true //99

100 - undefined //NaN
100 - null //100

物件型態

在物件形態下會透過物件的 valueOf() 方法取的對應值
如果物件沒有 valueOf() 則透過 toString() 轉為字串後再以 Number() 嘗試將數值轉為數字後進行運算

1
100 - {} //NaN
1
2
3
4
5
6
7
8
9
10
11
12
13
14
//自訂物件,透過 Object.prototype.valueOf 來指定物件的 value
function Obj(num){
this.num = number;
}
Obj.prototype.valueOf = function(){
return this.num;
}

var o = new Obj(50);

100 - o //50

// 因為 o.valueOf() 的值為50

乘法/除法

乘法/除法則會將非數字值使用Number()轉換後在進行計算計算

1
2
3
4
5
6
7
8
100 * "10" //1000
100 * "abc" //NaN

100 * true //100
100 * false //0

100*{} //NaN

取餘數

取餘數則是使用除法運算後取到餘數,在Infinity狀況下都是NaN,如果遇到一搬數值且除數為Infinity狀況下,結果則為被除數

1
2
3
4
5
6
7
Infinity % 0 //NaN
Infinity % 100 //NaN
Infinity % Infinity //NaN
Infinity % -Infinity //NaN

100 % Infinity //100
0 % Infinity //0