感谢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中的引用能够帮助开发人员避免许多常见的错误,并编写出更好的代码。
编码快乐!!