ECMAScript 變量可能包含兩種不同數據類型的值:基本類型值和引用類型值。 基本類型值指的是簡單的數據段,而引用類型值指那些可能由多個值構成的對象。
5 種基本數據類型: Undefined、 Null、 Boolean、 Number 和 String。
這 5 種基本數據類型是按值訪問的,因為可以操作保存在變量中的實際的值。
引用類型的值是保存在內存中的對象。與其他語言不同,
JavaScript 不允許直接訪問內存中的位置,也就是說不能直接操作對象的內存空間。在操作對象時,實際上是在操作對象的引用而不是實際的對象。為此,引用類型的值是按引用訪問的。
動態的屬性
對於引用類型的值,我們可以為其添加屬性和方法,也可以改變和刪除其屬性和方法。
對象不被銷毀,設置的屬性和方法,將一直存在。
不能給基本類型的值設置屬性和方法。
復制變量值
如果從一個變量向另一個變量復制基本類型的值,會在變量對象上創建一個新值,然后把該值復制
到為新變量分配的位置上。
這兩個變量可以參與任
何操作而不會相互影響。(復制變量的值)
當從一個變量向另一個變量復制引用類型的值時,同樣也會將存儲在變量對象中的值復制一份放到
為新變量分配的空間中。不同的是,這個值的副本實際上是一個指針,而這個指針指向存儲在堆中的一
個對象。復制操作結束后,兩個變量實際上將引用同一個對象。因此,改變其中一個變量,就會影響另
一個變量。(復制的是引用指針)
傳遞參數
ECMAScript 中所有函數的參數都是按值傳遞的。也就是說,把函數外部的值復制給函數內部的參
數,就和把值從一個變量復制到另一個變量一樣。
訪問變量有按值和按引用兩種方式,而參數只能按值傳遞。
在向參數傳遞基本類型的值時,被傳遞的值會被復制給一個局部變量(即命名參數,或者用ECMAScript 的概念來說,就是 arguments 對象中的一個元素)。
1
2
3
4
5
6
7
8
|
function
addTen(num){
num +=10;
return
num;
}
var
count = 20;
var
result = addTen(count);
alert(count);
//20
alert(result);
//30
|
在向參數傳遞引用類型的值時,會把這個值在內存中的地址復制給一個局部變量,因此這個局部變量的變化會反映在函數的外部。傳給函數的是數值的一個引用,函數中對其屬性的修改外部可見,但用新引用覆蓋其則在外部不可見。
1
2
3
4
5
6
|
function
setName(obj){
obj.name =
"staven"
;
}
var
person =
new
Object();
setName(person);
alert(person.name); //staven
|
普通賦值
1
2
3
4
|
var
a = 1;
var
b = a;
//賦的是a的復制值
b ++;
alert(a);
//"1" b的修改不影響a
|
1
2
3
4
|
var
a = [1];
var
b = a;
//賦的是a的引用
b[0] ++;
alert(a);
//"2" b的修改對a也有效
|
參數傳值傳遞:傳給函數的是數值的一個復制,函數中對其的修改外部不可見
1
2
3
4
5
6
7
8
9
10
11
12
|
var
a = 1;
var
b = 2;
function
change(a,b) {
var
c = a;
a = b;
//用新引用覆蓋
b = c;
alert(a);
//"2"
alert(b);
//"1"
}
change(a,b);
alert(a);
//"1"
alert(b);
//"2"
|
1
2
3
4
5
6
7
8
9
10
11
12
13
|
var
a = [1, 2, 3];
var
b = [5, 6];
function
change(a,b) {
a[0] = 4;
//對其屬性的修改外部可見
var
c = a;
a = b;
//用新引用覆蓋
b = c;
alert(a);
//"5,6"
alert(b);
//"4,2,3"
}
change(a,b);
alert(a);
//"4,2,3"
alert(b);
//"5,6"
|
1
2
3
4
5
6
7
8
9
10
11
|
var
a = [1, 2, 3];
var
b = [5, 6];
function
change() {
var
c = a;
a[0] = 4;
a = b;
b = c;
};
change();
alert(a);
//"5,6"
alert(b);
//"4,2,3"
|
傳值的比較比較的是數值 而傳址的比較比較的是引用。
參數傳遞角度理解閉包
1
2
3
4
5
6
7
8
|
var
add_handlers =
function
(nodes) {
var
i;
for
(i = 0, l = nodes.length; i < l; i ++) {
nodes[i].onclick =
function
(e) {
alert(i);
// 當然這里的結果必然是每次alert的都是節點總數。。。。
}
}
};
|
此時i是父級函數作用域的變量的引用。給每個節點設置onclick事件的時候將i的引用傳遞給了alert,當我點擊節點觸發onclick事件的時候,i的值已經變成了節點總數。
1
2
3
4
5
6
7
8
9
10
11
|
var
add_handlers =
function
(nodes) {
var
i;
for
(i = 0, l = nodes.length; i < l; i ++) {
nodes[i].onclick =
function
(i) {
return function (){
alert(i);
}
}(i);
}
};
|
這樣修改后之所以正確是因為此時傳進去的是i的值的復制。
檢測類型
typeof 操作符是確定一個變量是字符串、數值、布爾值,還是 undefined 的最佳工具。如果變
量的值是一個對象或 null,則 typeof 操作符都會返回"object"。
如果變量是給定引用類型的實例,那么
instanceof 操作符就會返回 true。
1
2
3
4
5
6
7
8
|
function
setName(obj){
obj.name =
"staven"
;
obj =
new
Object();
obj.name =
"Bob"
;
}
var
person =
new
Object();
setName(person);
alert(person.name);
//staven
|