JavaScript引用是如何工作的


摘要:JavaScript中沒有指針,並且JavaScript中的引用與我們通常看到的大多數其他流行編程語言的工作方式不同。在JavaScript中,不可能有一個變量到另一個變量的引用。而且,只有復合值(例如對象或數組)可以通過引用來賦值。

整片文章中將使用下列屬於:

  • 標量–單個值或數據單元(如整數、布爾值、字符串)
  • 復合--由多個值組成(如數組、對象、集合)
  • 原始 - 直接的價值,而不是對包含值的東西的引用。
    JavaScript的標量類型是原語,不像其他一些語言(如Ruby)具有標量引用類型。注意,在JavaScript中,標量原始值是不可變的,而復合值是可變的。

概要:

1.分配給變量的值的類型決定該值存儲的是值還是引用。
2.在變量賦值的時候,標量原始值(Number,String,Boolean,undefined,null,Symbol)通過值來賦值,復合值通過引用來賦值。
3.JavaScript中的引用僅指向包含的值,不指向其他變量或引用。
4.在JavaScript中,標量原始值是不可變的,復合值是可變的。

通過值賦值的快速示例

在下面的代碼片段中,我們將一個標量原始值(一個數字)分配給一個變量,因此這里是通過值來賦值。首先,變量 batman被初始化,當變量superman被分配存儲在batman中的值的時候,實際上是創建了該值的一個副本並存儲在變量superman中。當變量superman被修改時,變量batman不會受到影響,因為它們指向不同的值。

var batman = 7;
var superman = batman;   //通過值來賦值
superman++;
console.log(batman);     //7
console.log(superman);   //8

通過值來賦值

通過引用賦值的快速示例

在下面的代碼片段中,我們將一個復合值(數組)賦值給一個變量,因此這里是通過引用賦值。變量flashquicksilver是相同的值(也稱為共享值)的引用。當修改共享值時,引用將指向更新的值。

var flash = [8,8,8];
var quicksilver = flash;   //通過引用來賦值
quicksilver.push(0);
console.log(flash);        //[8,8,8,0]
console.log(quicksilver);  //[8,8,8,0]

通過引用來賦值

如何創建一個新的引用

當變量中的復合值被重新賦值的時候,將創建一個新的引用。在JavaScript中,與大多數其他流行的編程語言不同是:引用指向存儲在變量中的值,不指向其他變量或者引用。

var firestorm = [3,6,3];
var atom = firestorm;   //通過引用來賦值
console.log(firestorm); //[3,6,3]
console.log(atom);      //[3,6,3]
atom = [9,0,9];         //通過值來賦值 (創建新的引用)
console.log(firestorm); //[3,6,3]
console.log(atom);      //[9,0,9]

創建一個新的引用

當引用作為函數參數傳遞時,引用如何工作

在下面的代碼片段中,變量magneto是一個復合值(一個數組),因此它作為一個引用被賦值給了變量x(函數參數)。

在IIFE中調用的Array.prototype.push方法會通過JavaScript引用來改變變量中的值。但是,變量x的重新賦值會創建一個新的引用,並且對變量x的進一步修改不會影響到變量magneto的引用。

var magneto = [8,4,8];
(function(x) {        //IIFE
    x.push(99);
    console.log(x);   //[8,4,8,99]
    x = [1,4,1];      //重新賦值變量 (創建一個新的引用)
    x.push(88);
    console.log(x);   //[1,4,1,88]
})(magneto);
console.log(magneto); //[8,4,8,99]

如何更改作為函數參數通過JavaScript引用傳遞的復合變量中的原始值

這里的解決方案是修改引用指向的現有復合值。在下面的代碼片段中,變量wolverine是一個復合值(一個數組)並且在IIFE中被調用,變量x(函數參數)是被賦值了一個引用。

可以通過將屬性Array.prototype.length的值設置為0來創建一個空數組。因此,變量wolverine通過JavaScript引用更改為變量x中的新值。

var wolverine = [8,7,8];
(function(x) {              //IIFE
    x.length = 0;           //創建空數組對象
    x.push(1,4,7,2);
    console.log(x);         //[1,4,7,2]
})(wolverine);
console.log(wolverine);     //[1,4,7,2]

如何通過按值賦值來存儲復合值

這里的解決方案是制作復合值的手動副本,然后將復制的值分配給變量。因此,分配值的引用不指向原始值。

創建一個(淺)復合值副本(數組對象)推薦調用Array.prototype.slice方法,而不傳遞任何參數。

var cisco = [7,4,7];
var zoom = cisco.slice();  //創建淺復制
cisco.push(77,33);
console.log(zoom);         //[7,4,7]
console.log(cisco);        //[7,4,7,77,33]

通過按值賦值來存儲復合值

如何通過按引用賦值來存儲一個標量初始值

這里的解決方案是將標量原始值包含在復合值(即對象或數組)中作為其屬性值。因此,它可以通過引用來賦值。在下面的代碼片段中,變量speed中的標量原始值設置為flash對象的屬性。因此,在調用IIFE的時候,它通過引用賦值給了x(函數參數)。

var flash = { speed: 88 };
(function (x) {             //IIFE
    x.speed = 55;
})(flash);
console.log(flash.speed);   //55

總結

很好地理解JavaScript中的引用可以幫助開發人員避免許多常見的錯誤,並編寫出更好的代碼。

編碼快樂!!

感謝Naveen Karippai先生允許我翻譯此文章,原文鏈接:https://www.sitepoint.com/how-javascript-references-work/


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM