JavaScript 中没有指针,并且 JavaScript 中的引用与我们通常看到的大多数其他流行编程语言的工作方式不同。在 JavaScript 中,不可能有一个变量到另一个变量的引用。而且,只有复合值(例如对象或数组)可以通过引用来赋值。
整片文章中将使用下列属于:
1、标量–单个值或数据单元(如整数、布尔值、字符串)
2、复合 -- 由多个值组成(如数组、对象、集合)
3、原始 - 直接的价值,而不是对包含值的东西的引用。
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
通过引用赋值的快速示例
在下面的代码片段中,我们将一个复合值(数组)赋值给一个变量,因此这里是通过引用赋值。变量 flash 和 quicksilver 是相同的值(也称为共享值)的引用。当修改共享值时,引用将指向更新的值。
- 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 中的引用可以帮助开发人员避免许多常见的错误,并编写出更好的代码。
编码快乐!!
免责声明: 杰微刊遵循行业规范,任何转载的稿件都会明确标注来源和链接。 转载目的在于传递更多信息,并不代表杰微刊赞同其观点和对其真实性负责。如涉及作品内容、版权和其它问题,请在 30 日内与本网联系,我们将在第一时间删除内容。
来源: http://www.open-open.com/lib/view/open1492141494673.html