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 相关文章推荐
js 编写规范
Mar 03 Javascript
分享20多个很棒的jQuery 文件上传插件或教程
Sep 04 Javascript
javascript 常用功能总结
Mar 18 Javascript
jQuery.prototype.init选择器构造函数源码思路分析
Feb 05 Javascript
js实现按一下删除键删除整个单词附demo
Sep 05 Javascript
jQuery实现滚动切换的tab选项卡效果代码
Aug 26 Javascript
JS实现title标题栏文字不间断滚动显示效果
Sep 07 Javascript
jQuery的Cookie封装,与PHP交互的简单实现
Oct 05 Javascript
ElementUI Tag组件实现多标签生成的方法示例
Jul 08 Javascript
使用Vue.set()方法实现响应式修改数组数据步骤
Nov 09 Javascript
vue-drag-chart 拖动/缩放图表组件的实例代码
Apr 10 Javascript
Jquery $.map使用方法实例详解
Sep 01 jQuery
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 strnatcmp()函数的用法总结
2013/11/27 PHP
从零开始学YII2框架(六)高级应用程序模板
2014/08/20 PHP
浅谈Laravel中的一个后期静态绑定
2017/08/11 PHP
PHP中散列密码的安全性分析
2019/07/26 PHP
js仿百度有啊通栏展示效果实现代码
2013/05/28 Javascript
使用js对select动态添加和删除OPTION示例代码
2013/08/12 Javascript
jquery获取div距离窗口和父级dv的距离示例
2013/10/10 Javascript
JS中typeof与instanceof之间的区别总结
2013/11/14 Javascript
用jquery模仿的a的title属性的例子
2014/10/22 Javascript
使用AOP改善javascript代码
2015/05/01 Javascript
JavaScript判断按钮被点击的方法
2015/12/13 Javascript
Vuejs第一篇之入门教程详解(单向绑定、双向绑定、列表渲染、响应函数)
2016/09/09 Javascript
Three.js快速入门教程
2016/09/09 Javascript
深入学习jQuery中的data()
2016/12/22 Javascript
ES6新特性二:Iterator(遍历器)和for-of循环详解
2017/04/20 Javascript
详解webpack+vue-cli项目打包技巧
2017/06/17 Javascript
JS实现弹出下载对话框及常见文件类型的下载
2017/07/13 Javascript
vue  自定义组件实现通讯录功能
2018/09/30 Javascript
Vue页面刷新记住页面状态的实现
2019/12/27 Javascript
[01:35]辉夜杯战队访谈宣传片—iG.V
2015/12/25 DOTA
[47:10]完美世界DOTA2联赛PWL S3 LBZS vs Rebirth 第二场 12.16
2020/12/18 DOTA
Python的Django框架中的数据过滤功能
2015/07/17 Python
Tensorflow加载预训练模型和保存模型的实例
2018/07/27 Python
python2和python3实现在图片上加汉字的方法
2019/08/22 Python
python opencv 图像边框(填充)添加及图像混合的实现方法(末尾实现类似幻灯片渐变的效果)
2020/03/09 Python
python爬虫开发之selenium模块详细使用方法与实例全解
2020/03/09 Python
Python enumerate() 函数如何实现索引功能
2020/06/29 Python
Python unittest基本使用方法代码实例
2020/06/29 Python
基于DOM+CSS3实现OrgChart组织结构图插件
2016/03/02 HTML / CSS
巴西网上药房:onofre
2016/11/21 全球购物
阿联酋彩妆品牌:OUD MILANO
2019/10/06 全球购物
英语自荐信常用语句
2013/12/13 职场文书
同学会邀请函模板
2015/01/30 职场文书
2016七夕情人节寄语
2015/12/04 职场文书
技术入股协议书
2016/03/22 职场文书
《月歌。》宣布制作10周年纪念剧场版《RABBITS KINGDOM THE MOVIE》
2022/04/02 日漫