JS中的變數賦值深入理解

admin發表於2020-06-17

簡單理解就是數字和字串是複製,物件和陣列是地址引用。但如果是引用,如果你對引數進行重新賦值的話,會改變引數引用的地址。函式外部的陣列或者物件就不會被修改。


在看到上面這句話之前,本來我是對變數賦值的概念還不是很理解的,因為最開始我就直接認為變數賦值就是字面上的複製;然而在最近的一次新專案開發中,遇到了一個變數賦值的問題,讓我對變數賦值的概念有了不一樣的理解,我就又直接的認為變數賦值就是地址引用。但是,這特麼也是錯誤的理解。雖然之前對這樣的理解充滿著疑惑,也沒有去查閱資料去解決心中的問題,就這樣讓這個知識點從我腦中遺失了。


由於最近幾天想腦補一下JS的基礎知識,提升自己的基礎知識水平,所以又重新開始翻閱各種資料追根朔源。今天在群裡的某大神幫助下,基本上算是比較透徹的理解了變數賦值。簡單的一句話,說出了變數賦值的原理:

[HTML] 純文字檢視 複製程式碼
簡單理解就是數字和字串是複製,物件和陣列是地址引用。但如果是引用,如果你對引數進行重新賦值的話,會改變引數引用的地址。
函式外部的陣列或者物件就不會被修改。

下面寫幾個例子,驗證一下JS的變數賦值到底是怎樣的。

[JavaScript] 純文字檢視 複製程式碼
var a = 3;
var b = a;
b++;
console.log(a);  // return 3;
console.log(b);  // return 4;
var c = 'string';
var d = c;
c += ' is String';
console.log(c);  // return 'string is String';
console.log(d);  // return 'string';

此時,從上面的例子可以看出,雖然b的值加1,但是a的值沒有改變,另外,c變數有一個字串拼接過程,但d的值沒有變化。從而說明數字和字串型別的變數賦值就是複製過程。


下面再驗證一下物件Object和陣列Array變數的賦值

[JavaScript] 純文字檢視 複製程式碼
var arr = [1,2,3];
var brr = arr;
brr.push(4);
console.log(arr);  // return [1,2,3,4]
console.log(brr);  // return [1,2,3,4]
var obj = {a: 1, b: 2};
var obj2 = obj;
obj.c = 3;
console.log(obj);  // return {a: 1, b: 2, c: 3};
console.log(obj2);  // return {a: 1, b: 2, c: 3};

此時,從上面的例子可以得出一個結論,那就是物件Object型別與陣列Array型別的變數賦值,是一個地址引用的過程。


接下來就是驗證一下對引數進行重新賦值,是否會改變引數引用的地址,而函式外部的陣列或者物件就不會被修改。

[JavaScript] 純文字檢視 複製程式碼
var arr = [1,2,3];
// function change(a) {
//	a.push(4);
//	return a;
//}
function set(a) {
	a = [3,2,1];
	return a;
}
//var brr = change(arr);
var crr = set(arr);
console.log(arr);  // return [1,2,3]
//console.log(brr);  // return [1,2,3,4]
console.log(crr);  // return [3,2,1]

從上面兩個例子的結果可以看出,陣列Array型別的變數賦值的確是地址的引用,然後如果作為一個函式的引數被引用後被重新賦值了,那麼函式外部的陣列或者物件就不會被修改了,因而引數引用的地址發生了改變。如果引用的引數在函式內並不是賦值,而是修改引數裡的某個屬性的話,則引數引用地址不會發生變化,外部的變數屬性值也會隨之發生變化。


接下來的物件Object型別的變數賦值跟陣列Array型別一樣,你可以親手去驗證一下,這裡不再舉例了。

相關文章