感謝Naveen Karippai先生容許我翻譯此文章,原文連接:https://www.sitepoint.com/how...javascript
摘要:JavaScript中沒有指針,而且JavaScript中的引用與咱們一般看到的大多數其餘流行編程語言的工做方式不一樣。在JavaScript中,不可能有一個變量到另外一個變量的引用。並且,只有複合值(例如對象或數組)能夠經過引用來賦值。java
整片文章中將使用下列屬於:編程
標量–單個值或數據單元(如整數、布爾值、字符串)數組
複合--由多個值組成(如數組、對象、集合)編程語言
原始 - 直接的價值,而不是對包含值的東西的引用。
JavaScript的標量類型是原語,不像其餘一些語言(如Ruby)具備標量引用類型。注意,在JavaScript中,標量原始值是不可變的,而複合值是可變的。函數
1.分配給變量的值的類型決定該值存儲的是值仍是引用。
2.在變量賦值的時候,標量原始值(Number,String,Boolean,undefined,null,Symbol)經過值來賦值,複合值經過引用來賦值。
3.JavaScript中的引用僅指向包含的值,不指向其餘變量或引用。
4.在JavaScript中,標量原始值是不可變的,複合值是可變的。ui
在下面的代碼片斷中,咱們將一個標量原始值(一個數字)分配給一個變量,所以這裏是經過值來賦值。首先,變量 batman
被初始化,當變量superman
被分配存儲在batman
中的值的時候,其實是建立了該值的一個副本並存儲在變量superman
中。當變量superman
被修改時,變量batman
不會受到影響,由於它們指向不一樣的值。編碼
var batman = 7; var superman = batman; //經過值來賦值 superman++; console.log(batman); //7 console.log(superman); //8
在下面的代碼片斷中,咱們將一個複合值(數組)賦值給一個變量,所以這裏是經過引用賦值。變量flash
和quicksilver
是相同的值(也稱爲共享值)的引用。當修改共享值時,引用將指向更新的值。atom
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中,與大多數其餘流行的編程語言不一樣是:引用指向存儲在變量中的值,不指向其餘變量或者引用。spa
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]
這裏的解決方案是修改引用指向的現有複合值。在下面的代碼片斷中,變量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中的引用能夠幫助開發人員避免許多常見的錯誤,並編寫出更好的代碼。
編碼快樂!!