本篇為 [JS201] 進階 JavaScript:那些你一直搞不懂的地方筆記之一。
先從變數開始談起
一、變數的資料型態
底下提到關於變數型態、型態如何判斷及差別
1. primitive type 原始型態
a. null
b. undefined
c. string
d. number
e. boolean
f. symbol(ES6)
2. 物件型態,其他的都是物件 object
a. array
b. function
c. date and more...
二、 js 裡面怎麼判斷型態:
1. 用 typeof
?確定嗎?
// 正常情況下這樣使用
console.log(typeof 10) // number
console.log(typeof 'hello') //string
2. 但是,不能保證使用 typeof
出來的東西會是所想的
// 恩,這裡很正常,上面有說了是 object
console.log(typeof []) // object
// 這裡是 fn
console.log(typeof function(){}) // function
3. js 裡有名的 bug,null 該是 null 而不是 obj,修了會影響很多沒人敢修...
console.log(typeof null) // 是 object,但應該是 null
4. 既然這樣,那用什麼比較準確呢?
a. 判斷 array:
要注意舊的瀏覽器上面沒有喔
console.log(Array.isArray([]))
b. 判斷 fn: typeof
即可
c. 更正確的判斷方式:
Object.prototype.toString.call()
console.log(Object.prototype.toString.call('1')) // object String,只要看後面那個就好囉
console.log(Object.prototype.toString.call([])) // object Array,看後面那個就好,是 arr
5. typeof
常見用法補充
// 用在檢查變數有沒有使用
console.log(a) // undefined
三、 primitive type & object 的差別?
primitive type is immutable 不會被改變
var str = 'hello'
str.toUpperCase() // 回傳的是新的字串,即使「看起來」像是改變 str,但不是!
console.log(str) // 會輸出 hello
// 這樣就很明顯了
var str = 'hello'
var newStr = str.toUpperCase()
console.log(str, newStr) // hello HELLO
但 object type 會被改變
讓你摸不透的 = 賦值
一、object type 底層運作概念,儲存位置與內容的關係
// 舉例而已,沒有這種 0x01: 的寫法喔
// 假設有一個記憶體位置叫做 0x01,裡面存一個
0x01: {
number: 10
}
obj: 0x01 // obj 指向的是記憶體位置
obj2: 0x01
var obj = {
number: 10
}
var obj2 = obj // 把 obj 的記憶體位置,複製過去 obj2 那裡
console.log(obj, obj2) // { number: 10 } { number: 10 }
obj2.number = 20 // 找到記憶體位置,把裡面的內容改成 20
console.log(obj, obj2) // { number: 20 } { number: 20 }
二、array 的特性也是一樣的喔
雖說是寫入記憶體位置,但這個例子有個小陷阱;注意用一個等號賦值的概念
var arr = []
var arr2 = arr // 在這裡,兩個 arr 都是同一個位置
console.log(arr, arr2) // [] []
arr2 = ['arr2'] // 把 arr2 存到「另一個」記憶體位置
console.log(arr, arr2) // [] [ 'arr2' ]
小結:
注意 obj.number 與 obj = { number: 10} 的差別;前者是直接改變記憶體的內容,後者是重新給一個記憶體位置。
三、使用一個等號時,就是賦值的概念,很重要唸三遍。
== 與 === 的差別
一、兩個等號轉換型態;三個等號是判斷型態
// 轉換型態
console.log(2 == '2') // true
// 判斷型態
console.log(2 === '2') // false
在這樣的情況下,每次都用三個等號,是最保險的做法。
// 不管陣列裡面有沒有內容,結果都會是 false
// 因為比較的是「記憶體位置」
var arr = []
var arr2 = []
console.log(arr === arr2) // false
在做等號比較時,其實是在看兩個東西是否指到同樣的記憶體位置
二、NaN: not a number
// 雖然是 not a number,但結果卻是 number,厲害了吧
console.log(typeof NaN) // number
1. 什麼時候會產生 NaN
var a = Number('hello')
console.log(a) // NaN
// 在說裡面沒有數字的意思
console.log(typeof a)
// 會出現 number,厲害了吧!
2. 記下來!這是 special case: NaN 不等於任何東西,甚至是自己
var a = Number('hello')
console.log(a === a) // false
console.log(NaN === NaN) // false
3. 如何判斷是否為 NaN?
var a = Number('hello')
console.log(isNaN(a)) // true
初次見面:let 與 const
ㄧ、ES6 引進新的宣告變數的方式:let & const
1. const: constant 常數;不可被改變的
// 一開始就要給值,給了以後也不能改變
const a = 10
PS var: variable 變數;可變的
2. 真正改變的,是記憶體位置,還是內容呢?
// 這裡改變的是「內容」,所以不會報錯
const obj = {
number: 1
}
obj.number =2
// 這裡改變的是記憶體位置,就會報錯了
const obj = {
number: 1
}
obj = {
number: 2
}