JavaScript 原始值和引用值(Value vs. Reference)

了解如何將對象,數組和函數複製並傳遞給函數。要知道引用時複製了什麼。理解原始值是通過複製值來進行複製和傳遞的。

這是基礎觀念,學習js時一定要知道的事情~

By Value

有5個資料類型 Boolean, null, undefined, String, Number。
我們可以稱它們為primitive types。

宣告變數 a 的時候,a的記憶體會有一個位置存放它
在指定 b 它的值等於 a 的時候,b也會建立一個記憶體位置存放它。a 和 b雖然值是一樣的,但是他們的記憶體位置是不同的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
var a = 3;
var b = a;

console.log(a, b);
// -> 3,3

var x = 10;
var y = 'abc'

var z = x;
var q = y;

x = 5;
y = 'def';

console.log(x, y, z, q);
// -> 5, 'def', 10, 'abc'

By Reference

資料類型 Array, Function, Object。
我們可以稱它為 Objects。

當宣告變數 a 為一個Object 的時候,記憶體位置會給他一個位置;在指令另一個變數 b 的值等同於 a 的時候,並不會再另外創建一個記憶體位置給 b,而是一樣指定同一個位置給 b,因此如果 a 的值改變的時候,b也會跟著做變化,因為他們是參考同一個位置。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
var a = { name: 'Stoner' };
var b;
a = b;

console.log(a.name); //-> 'Stoner'
console.log(b.name); //-> 'Stoner'

a.name = "Rossi";

console.log(a.name); //-> 'Rossi'
console.log(b.name); //-> 'Rossi'

function changeName(obj) {
obj.name = 'Apple';
}

changeName(a);
console.log(a.name); //-> 'Apple'
console.log(b.name); //-> 'Apple'

/*------- 其他範例 A -------*/
function changeAgeAndReference(person) {
person.age = 25;
person = {
name: 'John',
age: 50
};

return person;
}

var personObj1 = {
name: 'Alex',
age: 30
};

var personObj2 = changeAgeAndReference(personObj1);

console.log(personObj1); // -> { name: 'Alex', age: 25 }
console.log(personObj2); // -> { name: 'John', age: 50 }


/*------- 其他範例 B -------*/
var personObj1 = {
name: 'Alex',
age: 30
};

var person = personObj1;
person.age = 25;

person = {
name: 'John',
age: 50
};

var personObj2 = person;

console.log(personObj1); // -> { name: 'Alex', age: 25 }
console.log(personObj2); // -> { name: 'John', age: 50 }

/*------- 其他範例 C -------*/
var obj = {
innerObj: {
x: 9
}
};

var z = obj.innerObj;

z.x = 25;

console.log(obj.innerObj.x);
//-> 25

/*------- 其他範例 D -------*/
var obj = {
arr: [{ x: 17 }]
};

var z = obj.arr;

//是使用 object literal 的方式來建立物件,則會變成 by Value,新增了一個記憶體的位置。
z = [{ x: 25 }];

console.log(obj.arr[0].x);
//-> 17

/*------- 其他範例 E -------*/
var obj = {};
var arr = [];
obj.arr = arr;
arr.push(9);
obj.arr[0] = 17;

console.log(obj.arr === [17]);
//-> false

/*------- 其他範例 F -------*/
function fn(item1, item2) {
if (item2 === undefined) {
item2 = [];
}

item2[0] = item1;

return item2;
}

var w = {};
var x = [w];
var y = fn(w);
var z = fn(w, x);

console.log(x === y);
//-> true

加強補充範例
是使用 object literal 的方式來建立物件,則會變成 by Value,新增了一個記憶體的位置。

1
2
3
4
5
6
7
8
var a = { name: 'Stoner' };
var b = a;
console.log(a.name); //-> 'Stoner'
console.log(b.name); //-> 'Stoner'

a = { name: 'Big Bird' };
console.log(a.name); //-> 'Big Bird'
console.log(b.name); //-> 'Stoner'

參考資料

Value vs. Reference
[筆記] 談談JavaScript中by reference和by value的重要觀念
[筆記] 談談JavaScript中的物件建立(Object) - Part 2 | 利用大括號{}建立物件

0%