摘要: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/

JavaScript引用是如何工作的的更多相关文章

  1. JavaScript引用方法说明

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  2. JavaScript中this的工作原理以及注意事项

    在JavaScript中,this 的概念比较复杂.除了在面向对象编程中,this 还是随处可用的.这篇文章介绍了this 的工作原理,它会造成什么样的问题以及this 的相关例子. 要根据this  ...

  3. 我所犯的JavaScript引用错误

    近期在w3cschool学习JavaScript和php--学完后,开始帮一哥们友情写网站.但是在使用ajax和Jquery的时候发现,我自己写的脚本不能运行.捣鼓了半天,没有发现任何语句错误.调试器 ...

  4. javaScript中闭包的工作原理

    一.什么是闭包? 官方”的解释是:闭包是一个拥有许多变量和绑定了这些变量的环境的表达式(通常是一个函数),因而这些变量也是该表达式的一部分.相信很少有人能直接看懂这句话,因为他描述的太学术.其实这句话 ...

  5. JavaScript的计时器的工作原理

    最近都在看一些JavaScript原理层面的文章,恰巧看到了jQuery的作者的一篇关于JavaScript计时器原理的解析,于是诚惶诚恐地决定把原文翻译成中文,一来是为了和大家分享,二来是为了加深自 ...

  6. The Cost of JavaScript --------引用

    tl;dr: 想要保持页面的快速运行,你需要仅加载当前页面所需的 JavaScript 代码.优先考虑用户所需,之后运用代码分离懒加载其他内容. Is it happening - 在这个时期,你可以 ...

  7. JavaScript 引用数据类型

    目录 1. 问题描述 2. 原因分析 3. React 中的引用数据类型 4. 业务场景 5. 参考资料 1. 问题描述 今天在写一个代码题时候, 有一个BUG 导致自己停滞好久, 该BUG 可以描述 ...

  8. 前端优化分析 之 javascript引用位置优化

    在很多优化法则中都提到,尽量将javascript放到页面底部,这是为什么呢 我通过firebug进行了下简单的分析 看下图  本页面首尾都存在javascript代码 我们分析得出 1.整个页面文档 ...

  9. 详解javascript中this的工作原理

    在 JavaScript 中 this 常常指向方法调用的对象,但有些时候并不是这样的,本文将详细解读在不同的情况下 this 的指向. 一.指向 window: 在全局中使用 this,它将会指向全 ...

随机推荐

  1. 基于Hadoop的改进Apriori算法

    一.Apriori算法性质 性质一: 候选的k元组集合Ck中,任意k-1个项组成的集合都来自于Lk. 性质二: 若k维数据项目集X={i1,i2,-,ik}中至少存在一个j∈X,使得|L(k-1)(j ...

  2. 概念 : 用户>角色>权限 的管理(Role-Based Access Control)

    RBAC 用户管理规范 概念:每个user有多个accounts,每个account 有一个account binding,有多个roles和多个tasks 举个例子:某个用户现在manager,这是 ...

  3. Alamofire源码解读系列(四)之参数编码(ParameterEncoding)

    本篇讲解参数编码的内容 前言 我们在开发中发的每一个请求都是通过URLRequest来进行封装的,可以通过一个URL生成URLRequest.那么如果我有一个参数字典,这个参数字典又是如何从客户端传递 ...

  4. 隐马尔可夫模型(HMM)攻略

    隐马尔可夫模型 (Hidden Markov Model,HMM) 最初由 L. E. Baum 和其它一些学者发表在一系列的统计学论文中,随后在语言识别,自然语言处理以及生物信息等领域体现了很大的价 ...

  5. Svm相关

    Svm相关: 1)  SVM方法是通过一个非线性映射p,把样本空间映射到一个高维乃至无穷维的特征空间中(Hilbert空间),使得在原来的样本空间中非线性可分的问题转化为在特征空间中的线性可分的问题. ...

  6. CRUD操作(20161017)

    上午: (7)范围查询 select * from car where price>40 and price<60 select * from car where price betwee ...

  7. C# 使用 USB转串 接收数据 问题

    C# 使用 USB转串 接收数据的 问题 硬件设备是MicroUSB接口,通过USB转串驱动接入PC机.自己用winForm写了一个读取串口数据的小程序,总是接收不到数据. 用传sscom32串口工具 ...

  8. 分享小知识:善用Group By排序

    以下列举了公用表/临时表/聚合函数三个因素为例子(覆盖索引因素除外,有利用此类索引都会以索引顺序)  环境: Microsoft SQL Server 2014 (SP1-GDR) (KB319472 ...

  9. 跑马灯、短信与反射EditText

    1.1.跑马灯功能 Android自带支持跑马灯功能,实现此功能需要设置已下属性: android:ellipsize="marquee" // 必选,跑马灯样式 android: ...

  10. Spring Boot 整合 Mybatis 实现 Druid 多数据源详解

    摘要: 原创出处:www.bysocket.com 泥瓦匠BYSocket 希望转载,保留摘要,谢谢! “清醒时做事,糊涂时跑步,大怒时睡觉,独处时思考” 本文提纲一.多数据源的应用场景二.运行 sp ...