JS 變量類型
JS 變量類型分為基本類型和引用類型
基本類型:基本類型有 Undefined,String,Number,Boolean,Null;按值訪問,可以直接操作保存在變量的實際值。存儲方式棧存儲。
基本類型在復制值的時候,會在變量對象上創建一個新的值,然后把這個值復制到新變量分配的位置上面來
引用類型:保存在內存中的對象,JS 不允許直接訪問變量內存的位置,就是說不能直接操變量內存空間。存儲方式是堆內存。引用類型可以添加屬性和方法。
引用類型在復制值的時候,同樣會將存儲在變量對象中的值復制一份放到新變量的分配的空間上面,但是不同的是,這個值實際上就是一個副本發指針,這個指針指向存儲子堆中的一個對象,實際上是兩個變量引用的是同一個對象,改變其中一個變量,也會影響另外的一個變量。
函數的參數傳遞是按照值訪問的
當傳遞的參數是基本數據類型的時候
let age = 20;
function Persion(age) {
age = ++ age;
return age;
}
Person(age); // 21
console.log(age); // 20
當傳遞的參數是引用類型的時候,傳遞的參數是一個對象的時候:
let pre = new Object();
function Person(obj) {
obj.name = 'Job';
}
Person(pre) // Job
let pre = new Object();
function Person(obj) {
obj.name = 'Job';
obj = new Object();
obj.name = 'Alean';
}
Person(pre) // Job
在這個 Person 函數內部存在的的 obj 是一個局部變量,外面的 pre 是全局的變量,因為 obj 和 pre 引用的是同一個對象,在函數內部為 obj 添加屬性的時候,外面的全局對象也跟著作出類反映。
為什么 pre.name 不是 Alean?
說明函數的參數傳遞是值傳遞,當函數的內部重寫 obj 的時候,這個變量引用的是一個局部對象,這個局部對象在函數執行完以后就銷毀類。
函數參數 obj 傳遞的是對象的引用(而不是 pre 對象本身),語句 obj = new Object() 是改變局部變量 obj 的引用,以后的修改不影響對象 pre 。
函數的參數(變量引用 obj)可以看作是一個局部變量。
一個容易混淆的地方
let o = { x: 1 };
let n = o;
n.x = 3;
console.log(n, o); // {x: 3} {x: 3}
o = { x: 2 };
console.log(n, o); // {x: 3} {x: 2}
第一行將 o 指向對象 {x: 1},第二行將 n 指向 o 指向的對象,第三行改變 n 所指向的對象的屬性也就相當于改變 o 指向的對象的屬性,而第五行只是改變 o 的指向(o = { x: 2 }),n 的指向并沒有改變(繼續指向 { x: 3 })。注意,這里不是給對象賦值,是改變指向。