JavaScript中变量、指针和引用功能与操作示例


Posted in Javascript onAugust 04, 2018

本文实例讲述了JavaScript中变量、指针和引用功能与操作。分享给大家供大家参考,具体如下:

1、变量

我们可能产生这样一个疑问:编程语言中的变量到底是什么意思呢?

事实上,当我们定义了一个变量a时,就是在存储器中指定了一组存储单元,并将这组存储单元命名为a。变量a的值实际上描述的是这组存储单元中存放的具体信息。

例如,在JS中

var a;
a=10;

第一个语句在存储器中指定了一组存储单元,并命名为a;

第二个语句在这组存储单元中存储了数字10。

变量a的值为10实际上是说存储单元组a存储的信息是10。

假使我们再次对a进行复制操作:

a="hello";

这样a的值变成字符串”hello”。这很容易理解,我们将存储单元组a中存储的信息改为字符串”hello”,显然原先的数字10将被覆盖。

2、指针

假使我们在另一个变量b中存储变量a在存储器的地址,会发生什么?

我们很容易想到,直接访问b变量,得到的并不是变量a的值,而是变量a在存储器中的地址,变量b便被称为指针。

这样一个问题产生了:如何通过变量b访问到变量a的值呢?

在C语言中,常用的是用*,比如:

int c=10,b;
int *p;/*p是指向int类型的指针*/
p=&c;/* &c获取变量c的地址,然后赋值给变量p,这样p存储的是变量c的地址,即p是指向c的指针*/
b=*p;/* *p访问p指向的对象,然后将值赋值给b*/

在JS中,并没有指针这种变量类型,但指针的应用却无处不在。比如:

var o1={b:1};
var o2={b:1};
o1===o2;//false
o1==o2;//false

这里o1和o2都是相同的对象,为什么不相等呢?这就需要深入理解JavaScript中的引用类型和指针。

首先,我们需要明白:

给o1和o2赋值,并不是o1地址中存储对象{b:1},o2地址中也存储对象{b:1}

其次,我们要明白实际发生的操作:

var o1={b:1}实现了在堆内存中创建了一个对象{b:1},o1则存储了该对象在堆内存中的地址,即o1是一个指针,指向{b:1};

同理,var o2={b:1}也在堆内存中创建了一个对象{b:1},o2存储了该对象在堆内存中的地址,即o2也是一个指针,指向{b:1};

并且,由于两个相同的对象{b:1}是先后创建,在堆内存中也不是存储在相同的地址。

然后,我们还需要知道:

在JavaScript中,引用类型(对象、数组、正则、Date、函数)的比较,实际上是比较指针是否指向存储器中的同一段地址,只有指向同样的地址才能相等。

显然,o1这个指针指向堆内存中创建的第一个对象{b:1};

o2指针则指向堆内存中创建的第二个对象{b:1};

但两个对象相对独立,并不是同一个对象,故o1和o2并没有指向同样的堆内存地址,故而并不相等。

我们再看常见的应用:

var o={a:1};
o.__proto__===Object.prototype;//true

对象o的构造函数是Object,Object有一个prototype属性,并且prototype是一个指针,他指向存储器中的一个对象,此对象将会被由构造函数创建的对象实例所共享。

作为Object的实例,o也有一个指针__proto__,它也指向Object的prototype属性指向的对象。

这里的全等返回true,则清楚地表明了两者指向同样的堆内存地址,即指向的是同一个对象。

我们如果想主动让两个引用类型指向同样的对象,如何操作呢?

var obj1={b:1};
var obj2=obj1;
obj1===obj2;//true
obj1==obj2;//true

可以看到,对于引用类型,直接使用'='赋值实际上就是使两者指向同一个对象。
故而,我们猜测,如果通过obj1修改了对象的值,obj2再次访问时将看到修改后的对象:

obj1.name='ls';
obj1;//{b: 1, name: "ls"}
obj2;//{b: 1, name: "ls"}

的确如此。作为对比:

o1.name='ls';
o1;//{b: 1, name: "ls"}
o2;//{b: 1}

那么,对于基本类型呢?

var s1=1;
var s2=2;
s1===s2;//true

在JS中,对于基本类型,只需其值相等,则两个变量就相等。

3、引用

首先,我们要深入理解引用类型的值。

前面我们看到,obj1和obj2指向堆内存中存储的同一个对象。当我们访问obj1和obj2时,都会返回同一个对象。可以说:obj1的值和obj2的值相同。

对于o1和o2,他们指向堆内存中不同地址的两个{b:1}对象,o1和o2拥有不同的值。

因此,对于引用类型,我们所说的值,指的是保存在内存中的对象。如果是同一对象,则值相同,不同对象则值不同。

在JS中,传递参数都是按值传递的。比如:

var a1=1,b1=2;
function add(a,b){
  a++;
  b--;
  return a+b;
};
add(a1,b1);//3
a1;//1
b1;//2

这里,函数add中的形参a、b分别得到变量a1、b1的值的拷贝,这便是按值传递。

在add函数执行环境中对a、b操作不会影响到全局变量a1、b1。

再看引用类型:

function setName(obj){
   obj.name="Nicholas";
   obj=new Object();
   obj.name="Greg";
}
var person=new Object();
setName(person);
alert(person.name);//"Nicholas"

执行setName(person)时,person指向的内存中的地址便被传入obj,使得obj也指向同样的内存地址,即同一个对象。这里的按值传递,传递的是内存地址。

如果通过obj修改该对象,外部访问person便也能体现出来。

我们可能有一个疑问,既然是指向同一个对象,为什么不是按引用传递呢?

首先,我们看到函数内部对obj重新进行了赋值,使得obj指向新创建的对象。如果是按引用传递,那么外部person便也会指向新创建的对象。实际上,person还是指向原先的对象。

对于引用类型的按值传递,其实可以更加通俗地理解:

1、实参将指向的内存地址传递给形参 ,按值传递的值指的是内存地址;
2、形参修改了它和实参共同指向的对象后,外部的实参会反映出来;
3、但形参始终无法修改实参指向的内存地址,即如果将形参指向新的对象,实参并不会指向新的对象。

基于以上3点,我们就不难理解上面代码运行的结果了。

希望本文所述对大家JavaScript程序设计有所帮助。

Javascript 相关文章推荐
给jQuery方法添加回调函数一款插件的应用
Jan 21 Javascript
Jquery中LigerUi的弹出编辑框(实现方法)
Jul 09 Javascript
Javascript 运动中Offset的bug解决方案
Dec 24 Javascript
浅谈javascript中字符串String与数组Array
Dec 31 Javascript
JavaScript里实用的原生API汇总
May 14 Javascript
简述JavaScript中正则表达式的使用方法
Jun 15 Javascript
jQuery+ajax实现滚动到页面底部自动加载图文列表效果(类似图片懒加载)
Jun 07 Javascript
jquery滚动条插件slimScroll使用方法
Feb 09 Javascript
react中fetch之cors跨域请求的实现方法
Mar 14 Javascript
vue裁切预览组件功能的实现步骤
May 04 Javascript
JS实现鼠标拖拽盒子移动及右键点击盒子消失效果示例
Jan 29 Javascript
详解vuex之store源码简单解析
Jun 13 Javascript
webpack4.x开发环境配置详解
Aug 04 #Javascript
微信小程序实现收藏与取消收藏切换图片功能
Aug 03 #Javascript
解决mpvue + vuex 开发微信小程序vuex辅助函数mapState、mapGetters不可用问题
Aug 03 #Javascript
mpvue跳转页面及注意事项
Aug 03 #Javascript
JavaScript高级函数应用之分时函数实例分析
Aug 03 #Javascript
mpvue小程序仿qq左滑置顶删除组件
Aug 03 #Javascript
JavaScript中call和apply方法的区别实例分析
Aug 03 #Javascript
You might like
PHP合并两个数组的两种方式的异同
2012/09/14 PHP
解析Ubuntu下crontab命令的用法
2013/06/24 PHP
新手菜鸟必读:session与cookie的区别
2013/08/22 PHP
推荐10个提供免费PHP脚本下载的网站
2014/12/31 PHP
PHP单例模式详细介绍
2015/07/01 PHP
解决laravel查询构造器中的别名问题
2019/10/17 PHP
Jquery Ajax学习实例6 向WebService发出请求,返回DataSet(XML) 异步调用
2010/03/18 Javascript
改进UCHOME的记录发布,增强可访问性用户体验
2011/01/17 Javascript
JavaScript 继承使用分析
2011/05/12 Javascript
正则表达式中特殊符号及正则表达式的几种方法总结(replace,test,search)
2013/11/26 Javascript
js中call与apply的用法小结
2013/12/28 Javascript
javascript模拟php函数in_array
2015/04/27 Javascript
Js实现简单的小球运动特效
2016/02/18 Javascript
node.js插件nodeclipse安装图文教程
2020/10/19 Javascript
bootstrap表单按回车会自动刷新页面的解决办法
2017/03/08 Javascript
《javascript少儿编程》location术语总结
2018/05/27 Javascript
转换layUI的数据表格中的日期格式方法
2019/09/19 Javascript
html2canvas属性和使用方法以及如何使用html2canvas将HTML内容写入Canvas生成图片
2020/01/12 Javascript
Javascript Worker子线程代码实例
2020/02/20 Javascript
[59:36]2018DOTA2亚洲邀请赛 4.3 突围赛 Secret vs VG 第二场
2018/04/04 DOTA
[49:31]DOTA2-DPC中国联赛 正赛 Elephant vs LBZS BO3 第二场 1月29日
2021/03/11 DOTA
详细介绍Python函数中的默认参数
2015/03/30 Python
Python读取二进制文件代码方法解析
2020/06/22 Python
H5 meta小结(前端必看篇)
2016/08/24 HTML / CSS
expedia比利时:预订航班+酒店并省钱
2018/07/13 全球购物
Shell如何接收变量输入
2016/08/06 面试题
大学生求职简历的自我评价
2013/10/21 职场文书
初一科学教学反思
2014/01/27 职场文书
新闻编辑自荐书范文
2014/02/12 职场文书
军训感想500字
2014/02/20 职场文书
优秀团员事迹材料1500字
2014/08/31 职场文书
2015元旦晚会主持人开场白+结束语
2014/12/14 职场文书
2015年煤矿工作总结
2015/04/28 职场文书
只需要这一行代码就能让python计算速度提高十倍
2021/05/24 Python
php 文件上传至OSS及删除远程阿里云OSS文件
2021/07/04 PHP
Javascript中async与await的捕捉错误详解
2022/03/03 Javascript