iT邦幫忙

0

[學習筆記] JavaScript - Call by Value vs Call by Reference or Sharing?

  • 分享至 

  • xImage
  •  

本篇內容參考連結
PJCHENder

Data Type

首先必須了解, 在Javascript中, 有需多資料型別, 主要分成兩大類. 分別是基本型別(primitive type)和物件型別(Object).

  1. Primitive type:
    • Boolean
    • Null
    • Undefined
    • Number
    • BigInt
    • String
    • Symbol
  2. Object:
    • Array, function, map, ...etc

一般來說, Primitive type會是Call by Value, 而Object則是 Call by Reference. 接下來會用幾個程式範例來解釋.

Call by Value

直接來看簡單的範例, 先建立一個變數 a 並賦予值 3. 再來建立變數 b, 並把b的值等於a. 最後再把 a 的值改成2.

var a = 3;
var b;

b = a;
a = 2;

console.log(a);
console.log(b);

再來我們看到結果很直觀的呈現

a is 2
b is 3

由此可知道當把一個變數等於另一個變數時, 只把值賦予給另一個變數, 之後兩者是獨立的, 操作並不互相影響. 往更底層去了解的話, 即是當我們在建立 primitive type 的變數時, 會把他存在記憶體的某個地方(假設為 0x001), 而當我們宣告另一個變數, 並把前一個的值賦予給他的時候, 他其實會建立自己的記憶體位址(假設為 0x002). 所以當之後操作的時候, 因為本身就處於不同的記憶體位址, 所以不會互相干擾. 這個就是所謂的 Call by Value.

Call by Value 大部分都會發生在 primitive type 的變數

Call by Value

Call by Reference

直接來看簡單的範例, 先建立一個變數 a 並賦予一個Object { text: "Hello"}. 再來建立變數 b, 並把b的值等於a. 最後再把 a 裡的Property text的值改成Hi.

var a = { text: "Hello"};
var b;

b = a;
a.text = "Hi";

console.log(a);
console.log(b);

結果b的值也一起被更新了

{ text: 'Hi' }
{ text: 'Hi' }

當變數為Object時, 賦予給先的變數. 兩者會相依, 在之後的操作也會互相影響. 從記憶體的方面來說, 當建立a時, 會存在位址(假設為 0x001). 而當建立b並把a的值賦予b時, 這時候並不會再給他一個新的位址, 而是把b指定到相同位址(0x001). 所以當在操作更改值時, 從變數a或變數b, 其實都是對存在位址0x001的值做操作, 所以才會更改a的時候, b也一起被更新. 這個就是所謂的 Call by Reference.

Call by Reference 大部分都會發生在 Object 的變數

Call by Reference

Call by Reference - Additional Information

等於(== 或是 ===)被用reference type上, 則會比較reference不會是value. 參考以下例子

var a = { text: "Hello"};
var b;

console.log(a == b); // true

var c = { text: "Hello"};
var d = { text: "Hello"};

console.log(c == d); // false

所以在比較時, 可以先把其轉成primitive type: string

var c = { text: "Hello" };
var d = { text: "Hello" };

console.log(c == d); // false

var e = JSON.stringify({ text: "Hello" });
var f = JSON.stringify({ text: "Hello" });

console.log(e == f); // true

Call by Sharing

這次來看一個比較特別的例子, 對上面call by reference的例子做點修改, 這次不是更新Object裡的Property, 而是直接給一個新的Object.

var a = { text: "Hello" };
var b;
b = a;
a = { text: "Hi" };

console.log(a);
console.log(b);

這次結果則不會一起更新

{ text: 'Hi' }
{ text: 'Hello' }

當Object被重新賦予值時(並非更新Property), 則會記憶體給予一個新個位置. 事實上, Javascript不屬於單純的by value 或是 by Reference. 更準確來說就是Call by sharing. 所以當Object被重新賦值時, 基本上就會跟Pass by Value的結果一模一樣. 當Object僅內容被更新時, 則會回到call by reference的結果.


圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言