JavaScript数据操作_浅谈原始值和引用值的操作本质


Posted in Javascript onAugust 23, 2016

我的一句话总结:原始值不管是变量赋值还是函数传递都不会改变原值,引用值不管是变量赋值还是函数传递,如果新变量重新赋值,则不会影响原引用值,如新变量是直接操作,就会影响原引用值。

首先明确,值和类型是两个不同的概念。例如,null是null类型的唯一值、undefined是undefined类型的唯一值、而true和false是boolean类型仅有的两个值等。在任何语言中,值的操作都可以归纳为以下3个方面。

复制值:即把值赋值给新变量,或者通过变量把值赋值给另一个变量、属性或数组元素。

传递值:即把值作为参数传递给函数或方法。

比较值:即把值与另一个值进行比较,看是否相等。

由于值类型数据和引用型数据的值存在形式不同,自然操作它们的方法和所产生的结果也是不同的。注意,当值为值类型数据时,我们常称之为原始值或基本值;当值为引用型数据时,我们常称之为引用值或复合值。

1.使用原始值

对于原始值来说,其操作的3个层面说明如下。

1)复制值

在赋值语句中,操作的过程将会产生一个实际值的副本,副本的值和实际值之间没有任何联系,它们独自位于不同的栈区或者堆区。这个副本可以存储变量、对象的属性和数组的元素。例如:

var n = 123, a, b = [], c = {}; 
a = n;         // 复制数字123 
b[0] = n;        // 复制数字123 
c.x = n;        // 复制数字123 
(a == b[0]) && (a == c.x) && (b[0] == c.x) && alert("复制的值都是相等的");  // 检测它们的值都是相等的

在上面示例中,分别把值123复制3份给变量a、数组b和对象c,虽然它们的值是相等的,但是它们之间是相互独立的。

2)传递值

当把值传递给函数或方法时,传递的值仅是副本,而不是值本身。例如,如果在函数中修改传递进来的值时,结果只能够影响这个参数值的副本,并不会影响到原来的值。

var a = 123;    // 原来的值 

function f(x){ 
  x = x + x; 
} 
f(a);      // 调用函数修改传递的值 

alert(a);   // 查看变量a的值是否受影响,返回值为123,说明没有变化

3)比较值

在上面的示例中我们也可以看到,当对原始值进行比较时,进行逐字节的比较来判断它们是否相等。比较的是值本身,而不是值所处的位置,固然比较的结果可能会相等,但只是说明它们所包含的字节信息是相同的。

2.使用引用值

对于引用值来说,其操作的3个层面说明如下。

1)复制值

在赋值语句中,所赋的值是对原值的引用,而不是原值副本,更不是原值本身。也就是说,进行赋值之后,变量保存的都是对原值的引用(即原值的存储地址)。当在多个变量、数组元素或对象属性中间复制时,它们都会与原始变量保存的引用相同。

所有引用具有相同的效力和功能,都可以执行操作,如果通过其中的一个引用编辑数据,这种修改将会在原值及其他相关引用中体现出来。例如:

var a = [1,2,3];  // 赋值数组引用 
b = a;         // 复制值 
b[0] = 4;      // 修改变量b中第一个元素的值 
alert(a[0]);     // 返回4,显示变量a中第一个元素的值也被修改为4

但是,如果给变量b重新赋予新值,则新值不会影响原值内容。例如:

var a = [1,2,3];  // 赋值数组引用 
b = a;         // 复制值 
b = 4;         // 为变量b重写赋值 
alert(a[0]);     // 变量a的内容保持不变

重复赋值实际上是覆盖变量对原值的引用,变为另一个值的副本或对其引用。所以不会对原值产生影响,演示示意图如图4-2所示。

JavaScript数据操作_浅谈原始值和引用值的操作本质

2)传递值

当使用引用将数据传递给函数时,传递给函数的也是对原值的一个引用,函数可以使用这个引用来修改原值本身,任何修改在函数外部都是可见的。例如:

var a = [1,2,3]; 
function f(x){ 
  x[0] = 4;   // 在函数中修改参数值 
} 
f(a);       // 传递引用值 
alert(a[0]);    // 返回4,原值发生变化

请注意,在函数内修改的是对外部对象或数组的引用,而不是对象或数组本身的值。在函数内可以使用引用来修改对象的属性或数组的元素,但是如果在函数内部使用一个新的引用覆盖原来的引用,那么在函数内部的修改就不会影响原引用的值,函数外部也是看不到的。

var a = [1,2,3]; 
function f(x){ 
  x = 4;    // 在函数中修改参数值 
} 
f(a);       // 传递引用值 
alert(a[0]);    // 返回1,原值不会发生变化

3)比较值

当比较两个引用值时,比较的是两个引用地址,看它们引用的原值是否为同一个副本,而不是比较它们的原值字节是否相等。当对两个不同值进行引用时,尽管它们具有相同的字节构成,但是这两个引用的值却是不相等的。

var a = new Number(1);  // 引用值a 
var b = new Number(1);  // 引用值b 
var c = a;        // 把a的引用赋值给c 
alert(a==b);       // 返回false 
alert(a==c);       // 返回true

所以,{} == {},[] == [],都返回false。因为引用地址不同。

总之,对于任何语言来说,使用值和使用引用都是数据操作的两种基本方法。当我们操作数据时,要采用什么方法来进行处理,主要看数据的类型。值类型和引用型数据参与运算的方式不同,值类型数据通过使用值来操作数据,而引用型数据使用引用来操作数据。运算方式的不同,自然所产生的结果也不同。我们不妨再看一个示例:

var s = "abc";         // 字符串,值类型数据 
var o = new String(s);     // 字符串对象,被装箱后的字符串 


function f(v){         // 运算函数 
  v.toString = function(){  // 修改参数的方法toString() 
    return 123; 
  }; 
} 

f(s);    // 传入值 
alert(s);  // 返回字符串"abc",说明运算没有对原数据造成影响 
f(o);    // 传入引用 
alert(o);  // 返回数值123,说明运算已经影响到原数据的内部结构

值类型是以实际值参与运算的,因此与原数据没有直接联系。而引用型以引用地址参与运算,计算的结果会影响到引用地址所关联的堆区数据块。但是,有一点例外,对于JavaScript的字符串来说,它的操作方法就比较复杂,详情请google!

以上这篇JavaScript数据操作_浅谈原始值和引用值的操作本质就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
在标题栏显示新消息提示,很多公司项目中用到这个方法
Nov 04 Javascript
判断一个变量是数组Array类型的方法
Sep 16 Javascript
javascript 按键事件(兼容各浏览器)
Dec 20 Javascript
JavaScript中用于四舍五入的Math.round()方法讲解
Jun 15 Javascript
AngularJS基础 ng-readonly 指令简单示例
Aug 02 Javascript
vuejs通过filterBy、orderBy实现搜索筛选、降序排序数据
Oct 26 Javascript
关于Vue.nextTick()的正确使用方法浅析
Aug 25 Javascript
ES10 特性的完整指南小结
Mar 04 Javascript
微信小程序自定义可滑动顶部TabBar选项卡实现页面切换功能示例
May 14 Javascript
使用微信SDK自定义分享的方法
Jul 03 Javascript
Vue中this.$nextTick的作用及用法
Feb 04 Javascript
maptalks+three.js+vue webpack实现二维地图上贴三维模型操作
Aug 10 Javascript
JavaScript DOM节点操作方法总结
Aug 23 #Javascript
EasyUI创建对话框的两种方式
Aug 23 #Javascript
ES6所改良的javascript“缺陷”问题
Aug 23 #Javascript
浅谈JavaScript 函数参数传递到底是值传递还是引用传递
Aug 23 #Javascript
如何利用JSHint减少JavaScript的错误
Aug 23 #Javascript
jQuery事件处理的特征(事件命名机制)
Aug 23 #Javascript
深入浅出 jQuery中的事件机制
Aug 23 #Javascript
You might like
php日期操作技巧小结
2016/06/25 PHP
thinkphp诸多限制条件下如何getshell详解
2020/12/09 PHP
JavaScript在IE中“意外地调用了方法或属性访问”
2008/11/19 Javascript
JavaScript截取字符串的Slice、Substring、Substr函数详解和比较
2014/03/20 Javascript
Jquery中扩展方法extend使用技巧
2014/08/24 Javascript
JavaScript驾驭网页-获取网页元素
2016/03/24 Javascript
即将发布的jQuery 3 有哪些新特性
2016/04/14 Javascript
AngularJS实现的省市二级联动功能示例【可对选项实现增删】
2017/10/26 Javascript
JavaScript时间戳与时间日期间相互转换
2017/12/11 Javascript
旺旺在线客服代码 旺旺客服代码生成器
2018/01/09 Javascript
web前端页面生成exe可执行文件的方法
2018/02/08 Javascript
微信小程序左滑动显示菜单功能的实现
2018/06/14 Javascript
vue获取元素宽、高、距离左边距离,右,上距离等还有XY坐标轴的方法
2018/09/05 Javascript
浅谈小程序globalData的那些事儿
2019/11/01 Javascript
vue tab滚动到一定高度,固定在顶部,点击tab切换不同的内容操作
2020/07/22 Javascript
Nuxt的路由动画效果案例
2020/11/06 Javascript
js实现简易计算器小功能
2020/11/18 Javascript
解决vue下载后台传过来的乱码流的问题
2020/12/05 Vue.js
python中将字典转换成其json字符串
2014/07/16 Python
Python3 socket同步通信简单示例
2017/06/07 Python
python之当你发现QTimer不能用时的解决方法
2019/06/21 Python
基于python读取.mat文件并取出信息
2019/12/16 Python
Python基础之函数原理与应用实例详解
2020/01/03 Python
Python图像处理库PIL的ImageEnhance模块使用介绍
2020/02/26 Python
python 成功引入包但无法正常调用的解决
2020/03/09 Python
英国手机零售商:Carphone Warehouse
2018/06/06 全球购物
澳大利亚优质的家居用品和生活方式公司:Bed Bath N’ Table
2019/04/16 全球购物
华为C++笔试题
2014/08/05 面试题
安全教育心得体会
2013/12/29 职场文书
工作交流会欢迎词
2014/01/12 职场文书
劳动模范事迹材料
2014/01/19 职场文书
小学三年级数学教学反思
2014/01/31 职场文书
药剂专业个人求职信范文
2014/04/29 职场文书
单位工作证明范本
2015/06/15 职场文书
导游词之崇武古城
2019/10/07 职场文书
CSS中妙用 drop-shadow 实现线条光影效果
2021/11/11 HTML / CSS