[ 筆記 ] JavaScript 進階 01 - 變數性質


Posted by krebikshaw on 2020-09-24

重點標記

  • JavaScript 有兩種資料型態:Primitive 跟 Object
  • Primitive 原始型態目前只有 6 種(undefined、null、string、number、boolean、symbol),只要不屬於這 6 種,通通歸類在 Object 物件型態
  • Primitive 有 Immutable 的特性,可以把變數重新賦值,但不能用函式去改變數值
  • Primitive 直接存放數值,Object 存放記憶體位置
  • Object.prototype.toString.call(變數) 可以檢查資料型態

Primitive & Object 原始類型與物件的差異

JavaScript 有兩種資料類型,分為:

  • Primitive: 原始 / 基本 ( 非物件 )
  • Object: 物件

Primitive 原始型態
Primitive Type 又可以再細分成六種:

  1. undefined
  2. null
  3. string
  4. number
  5. boolean
  6. symbol (ES6)

Object 物件型態
只要是非以上六種的類型,就是物件類型 Object Type :

  • Function
  • Array
  • Date

Primitive VS Object

( 一 )Primitive 是 Immutable: 原始形態不能改變
原始型態不能改變的意思是「 呼叫函式時,不會改變到原來的值 」,而是回傳一個新的值,看以下範例:

let str = 'hello';
let newStr = str.toUpperCase();
console.log(str, newStr); // => hello, Hello

let arr = [1];
arr.push(2);
console.log(arr); // => [1, 2]
  • 當 string 呼叫 .toUpperCase(),原本的 str 並不會改變,所以必須用一個新的變數 newStr 來接收回傳值。
  • 而 arr 呼叫 .push() 時,原本的 arr 就直接產生了變化。

物件型態 Object 雖然能夠改變,但還是要看函式的作用為何,有的函式只會把結果回傳成一個新陣列,例如: Array.concat()、Array.filter()…

( 二 )存值的方式不一樣

  • Primitive: 直接放值,各變數不會互相影響
  • Object: 存記憶體位置,會互相影響,但如果是重新賦值,則會重新再指定一塊新的記憶體位置
let arr = [];
let arr2 = arr;
arr.push('hey');
console.log('arr: ', arr); 
console.log('arr2: ', arr2);

// push 這個 method 會去找到 arr2 的記憶體位置,再進行改變 => 共享記憶體位置
// arr: ['hey']
// arr2: ['hey']


let arr3 = arr;
arr3 = ['yo'];
console.log('arr: ', arr); 
console.log('arr3: ', arr3);

// 將 arr3 重新賦值 => 指定新的一塊記憶體位置
// arr: ['hey']
// arr2: ['yo']

所以差別在於:

  • 第一種做法 arr.push,是去 arr 的記憶體位置找到 arr 的值並改變。
  • 第二種做法 賦值( arr3 = ['yo'] ),是先重新畫一塊記憶體放值 ['yo'],再改變 arr3 存的記憶體位置,可以當成一個地址,指向 ['yo'] 這個值。

( 三 )比較的方式不一樣 ===
Primitive: 直接比較數值,Object 比較的方式是看「 記憶體位置 」

console.log([] === []); // false
console.log({} === {}); // false
console.log([1, 2, 3] === [1, 2, 3]); // false

console.log(NaN === NaN); // 特殊例子,NaN 永遠不會等於自己,要比對可以用 isNaN()

== VS ===
最大的差別就是 == 會做類型轉換,所以還是盡量都用 === 做比對

詳細可以參考 JavaScript Equality table 網站看各種類型比對的結果。

( 四 )const 常數的運用
常數的規則是一但賦值後就不能改變,但 不能變的是「 記憶體位置 」,而因為 Object 存的是記憶體位置,所以同樣地址的內容其實是可以改變的。

const obj = {
    number: 1
};

obj.number = 2; // => 沒問題,可以更改內容

obj = {
    number: 2; // => 賦值會改變記憶體位置,所以跳出錯誤訊息
}

檢查資料類型

typeof : 檢查資料類型
如果不清楚某資料是哪種資料類型,可以用 typeof 進行檢查。

但要注意的一點是,typeof 出來的答案可能會跟預期的不一樣,如果想用個更可靠的方法來檢查的話,可以用 Object.prototype.toString.call(變數)

typeof 的另一個作用可以拿來檢查變數是否存在
如果對一個未宣告或未賦值的變數做 typeof,會回傳 'undefined' ( 是字串 )
所以有些時候可以拿 typeof 來檢查變數是否存在。

if (typeof a !== 'undefined') {
    console.log(a); // => 確定 a 存在且有賦值,再進行對 a 的操作
}









Related Posts

[MTR04] W1 D2 Git 基本指令

[MTR04] W1 D2 Git 基本指令

MTR04_0627

MTR04_0627

[JavaScript] ES6:Destructuring 解構

[JavaScript] ES6:Destructuring 解構


Comments