javascript中的变量是传值还是传址的?


Posted in Javascript onApril 19, 2010

这个标题念起来有点拗口,但却是理解数据结构的关键。标题中的4个术语,对应的英文分别是:shallow copy(注意,不是shadow copy)、deep copy、pass by value、pass by reference(或pass by address)。传址和传引用是一回事。

一门编程语言的核心是数据结构,粗略来讲,可以把数据结构分成不可变类型(immutable)和可变类型(mutable)。为什么这么分呢?这涉及到内存分配问题。对于不可变类型,只要分配有限的内存空间即可,而对于不可变类型,理论上则要分配没有大小限制的空间。因此,这么分是出于合理利用系统资源的考虑。实际上,堆内存和栈内存分别用于保存不可变类型值和可变类型值。

什么是不可变类型?就是该值一旦赋予某个变量,就只属于某个变量,不能同属于其他变量。如:

window.onload=function() 
{ var stringValue = "淡淡的"; 
var anotherStringValue = stringValue; 
stringValue = "I have changed"; 
alert(stringValue);// 输出 I have changed 
alert(anotherStringValue);// 输出 淡淡的

此时,anotherStringValue中保存的值会不会也变成“I have changed”?不会。因为

var anotherStringValue = stringValue;

照stringValue中保存的字符串的原样,复制一个字符串(相应地,在内存中分配一块新空间),并将该字符串赋给anotherStringValue。换句话说,这两个变量虽然保存的值相同,但它们的值并不在一块内存中。因此,修改任何一个变量,都不会影响另一个变量。即

stringValue = “I have changed”;

只会影响stringValue的值。但是,确切来讲,stringValue = “I have changed”;并不是修改stringValue,而是创建了一个新字符串(相应地,在内存中分配一块新空间),然后让stringValue引用该字符串——更像是替换变量的值;原来的字符串呢?因为没有变量引用它,也就成为垃圾了(当然,垃圾所占用的内存会被回收)。

由此可见,赋值操作对于不变类型而言,传递的是内存中的值本身。那么,对于可变类型呢?当然,传递的是内存中值的引用(或者说地址),而且无论传递多少次,内存中始终都只有一份原始值——毕竟可变类型大小莫测,只保存一份原始值能最大限度节省内存空间。例如:

window.onload=function() 
{ 
var objectValue = {1:1,'s':'string','innerObject':{'innerArray' : [1,2,3]}}; 
var anotherObjectValue = objectValue; 
objectValue[1] = 100; 
alert(anotherObjectValue[1]); //输出 100 }

不言自明,这里的anotherObjectValue通过赋值操作,从objectValue那里只获得了对原始对象( {1:1,'s':'string','innerObject':{'innerArray' : [1,2,3]}})的引用,也就是该对象在内存中的地址,或者说“门牌号码”。因此,通过objectValue修改原始对象的第一个元素(objectValue[1] = 100;),结果同样会在anotherObjectValue[1]那里得到反映——因为这两个变量共享同一份原始值。

在JavaScript中,给函数传递参数是按照上述默认约定——即对不可变类型,传值;对可变类型,传址——进行的。如:

function example(str, obj){
……
}
example(stringValue,objectValue);

调用example函数时,第一个参数传递的是实际的字符串值,第二参数传递的是对象的引用(内存地址)。

Javascript 相关文章推荐
Javascript 生成指定范围数值随机数
Jan 09 Javascript
一个简单的Ext.XTemplate的实例代码
Mar 18 Javascript
jQuery移除tr无效的解决方法(tr是动态添加)
Sep 22 Javascript
jQuery通过写入cookie实现更换网页背景的方法
Apr 15 Javascript
基于Jquery插件实现跨域异步上传文件功能
Apr 26 Javascript
Angularjs 实现一个幻灯片示例代码
Sep 08 Javascript
详解webpack3如何正确引用并使用jQuery库
Aug 26 jQuery
详解React开发必不可少的eslint配置
Feb 05 Javascript
angularjs 的数据绑定实现原理
Jul 02 Javascript
Vue.js单向绑定和双向绑定实例分析
Aug 14 Javascript
微信小程序支付前端源码
Aug 29 Javascript
Node.js API详解之 console模块用法详解
May 12 Javascript
js获取当前select 元素值的代码
Apr 19 #Javascript
监控 url fragment变化的js代码
Apr 19 #Javascript
jquery获取input表单值的代码
Apr 19 #Javascript
编写高性能的JavaScript 脚本的加载与执行
Apr 19 #Javascript
jquery 关键字“拖曳搜索”之“拖曳”以及 图片“提示自适应放大”效果 的实现
Apr 18 #Javascript
jquery 新手学习常见问题解决方法
Apr 18 #Javascript
javascript 设计模式之单体模式 面向对象学习基础
Apr 18 #Javascript
You might like
中东人咖啡哲学
2021/03/03 咖啡文化
php+mysql 实现身份验证代码
2010/03/24 PHP
C#静态方法与非静态方法实例分析
2014/09/22 PHP
php判断类是否存在函数class_exists用法分析
2014/11/14 PHP
发一个自己用JS写的实用看图工具实现代码
2008/07/26 Javascript
nodejs中转换URL字符串与查询字符串详解
2014/11/26 NodeJs
jQuery on()方法示例及jquery on()方法的优点
2015/08/27 Javascript
Javascript中的数据类型之旅
2015/10/18 Javascript
AngularJS实践之使用ng-repeat中$index的注意点
2016/12/22 Javascript
原生JS实现《别踩白块》游戏(兼容IE)
2017/02/20 Javascript
js return返回多个值,通过对象的属性访问方法
2017/02/21 Javascript
实例分析nodejs模块xml2js解析xml过程中遇到的坑
2017/03/18 NodeJs
Vue2.0 实现歌手列表滚动及右侧快速入口功能
2018/08/08 Javascript
JavaScript原型对象原理与应用分析
2018/12/27 Javascript
详解vue 图片上传功能
2019/04/30 Javascript
python之yield表达式学习
2014/09/02 Python
Python 文件管理实例详解
2015/11/10 Python
Python模拟用户登录验证
2017/09/11 Python
pandas apply 函数 实现多进程的示例讲解
2018/04/20 Python
python实现桌面壁纸切换功能
2019/01/21 Python
python3+PyQt5 创建多线程网络应用-TCP客户端和TCP服务器实例
2019/06/17 Python
python中sort sorted reverse reversed函数的区别说明
2020/05/11 Python
Belvilla德国:在线预订度假屋
2018/04/10 全球购物
英国领先的维生素和补充剂品牌:Higher Nature
2019/08/26 全球购物
在子网210.27.48.21/30种有多少个可用地址?分别是什么?
2014/07/27 面试题
社会学专业学生职业规划书
2014/02/07 职场文书
申请任职学生会干部自荐书范文
2014/02/13 职场文书
《晚上的太阳》教学反思
2014/04/23 职场文书
主要负责人任命书
2014/06/06 职场文书
办理房产证委托书
2014/09/18 职场文书
国家领导干部党的群众路线教育实践活动批评与自我批评材料
2014/09/23 职场文书
办公室岗位职责
2015/02/04 职场文书
2015年南京大屠杀纪念日活动总结
2015/03/24 职场文书
公司更名通知函
2015/04/24 职场文书
负责培养人意见
2015/06/05 职场文书
适合后台管理系统开发的12个前端框架(小结)
2021/06/29 Javascript