問題分享:Js引用型別賦值

justcool發表於2019-03-03

今天在微信群裡有這樣一個問題和大家分享一下:

附上原始碼:

function changeAgeAndReference(person){
    person . age = 25;
    person = {
        nage : 'John',
        age : 50
    };
    return person ;
}
var personObj1={
    name : 'Alex',
    age : 30
}
var personObj2 = changeAgeAndReference(personObj1);
console.log(personObj1)
console.log(personObj2)
複製程式碼

會輸出什麼呢?答案是:

{name: "Alex", age: 25}
{nage: "John", age: 50}
複製程式碼

要理解答案為什麼是25和50 要理解Js變數賦值問題:

1. Js有兩類資料型別:值型別(基本型別)和引用型別

值型別(基本型別):字串(String)、數字(Number)、布林(Boolean)、對空(Null)、未定義(Undefined)、Symbol
引用資料型別:物件(Object)、陣列(Array)、函式(Function)。

基本資料型別是按值訪問的,因為可以操作儲存在變數中的實際的值; 引用型別的值是儲存在記憶體中的物件,在操作物件時,實際上是在操作物件的引用而不是實際的物件

2. 變數複製

基本型別複製:舉個栗子

var num1 = 5; 
var num2 = num1; 
複製程式碼

num1 中儲存的值是 5。當使用 num1 的值來初始化 num2 時,num2 中也儲存了值 5。但 num2 中的 5 與 num1 中的 5 是完全獨立的,該值只是 num1 中 5 的一個副本。此後,這兩個變數可以參與任 何操作而不會相互影響

問題分享:Js引用型別賦值

引用型別複製:舉個栗子

var obj1 = new Object(); 
var obj2 = obj1; 
obj1.name = "Nicholas"; 
alert(obj2.name); 
複製程式碼

變數 obj1 儲存了一個物件的新例項。然後,這個值被複制到了 obj2 中;換句話說,obj1 和 obj2 都指向同一個物件。這樣,當為 obj1 新增 name 屬性後,可以通過 obj2 來訪問這個屬性, 因為這兩個變數引用的都是同一個物件

問題分享:Js引用型別賦值

現在讓我們回到問題當中

function changeAgeAndReference(person){
    person . age = 25;
    person = {
        nage : 'John',
        age : 50
    };
    return person ;
}
var personObj1={
    name : 'Alex',
    age : 30
}
var personObj2 = changeAgeAndReference(personObj1);
console.log(personObj1)
console.log(personObj1)
複製程式碼

var personObj2 = changeAgeAndReference(personObj1) 相當於:

var person = personObj1 
複製程式碼

personObj1person 都指向同一個物件,改變person的屬性age也就改變了personObj1的age; 所以 personObj1 變為 {name: "Alex", age: 25}

函式內部:

person = {
  nage : 'John',
  age : 50
};
//相當於
var person = {
  nage : 'John',
  age : 50
};
複製程式碼

person被重新賦值,已經不指向之前的的物件了,所以return 的是 {nage: "John", age: 50}


文章參考:

《JavaScript 高階程式設計》中文譯本 第三版

相關文章