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的面向对象方法以及差别
Mar 31 Javascript
Mootools 1.2教程 排序类和方法简介
Sep 15 Javascript
node.js中的socket.io的广播消息
Dec 15 Javascript
js实现同一页面多个不同运动效果的方法
Apr 10 Javascript
JavaScript判断FileUpload控件上传文件类型
Sep 28 Javascript
浅谈JavaScript 执行环境、作用域及垃圾回收
May 31 Javascript
AngularJS实现分页显示数据库信息
Jul 01 Javascript
Vue.js使用v-show和v-if的注意事项
Dec 13 Javascript
Vue如何引入远程JS文件
Apr 20 Javascript
使用svg实现动态时钟效果
Jul 17 Javascript
bootstrap table列和表头对不齐的解决方法
Jul 19 Javascript
通过实例了解Render Props回调地狱解决方案
Nov 04 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
PHP脚本的10个技巧(5)
2006/10/09 PHP
用文本文件实现的动态实时发布新闻的程序
2006/10/09 PHP
解析php框架codeigniter中如何使用框架的session
2013/06/24 PHP
Thinkphp模板中截取字符串函数简介
2014/06/17 PHP
php数字运算验证码的实现代码
2015/07/30 PHP
Laravel关系模型指定条件查询方法
2019/10/10 PHP
如何让页面加载完成后执行js
2013/06/26 Javascript
jQuery实现鼠标可拖动调整表格列宽度
2014/05/26 Javascript
js实现键盘控制DIV移动的方法
2015/01/10 Javascript
javascript实现全局匹配并替换的方法
2015/04/27 Javascript
jQuery实现根据滚动条位置加载相应内容功能
2016/07/18 Javascript
Node.js实现兼容IE789的文件上传进度条
2016/09/02 Javascript
Angular-Touch库用法示例
2016/12/22 Javascript
手动初始化Angular的模块与控制器
2016/12/26 Javascript
EasyUI框架 使用Ajax提交注册信息的实现代码
2017/09/27 Javascript
基于Two.js实现星球环绕动画效果的示例
2017/11/06 Javascript
详解vue-router数据加载与缓存使用总结
2018/10/29 Javascript
JavaScript数值类型知识汇总
2019/11/17 Javascript
ng-alain的sf如何自定义部件的流程
2020/06/12 Javascript
[51:15]完美世界DOTA2联赛PWL S2 PXG vs Magma 第一场 11.21
2020/11/24 DOTA
pycharm 使用心得(二)设置字体大小
2014/06/05 Python
python3.4实现邮件发送功能
2018/05/28 Python
Python3列表内置方法大全及示例代码小结
2019/05/10 Python
Omio荷兰:预订火车、巴士和机票
2018/11/04 全球购物
幼儿园大班毕业感言
2014/02/06 职场文书
请假条范文大全
2014/04/10 职场文书
党的群众教育实践活动实施方案
2014/06/12 职场文书
计算机科学技术自荐信
2014/06/12 职场文书
机关干部四风问题自我剖析及整改措施
2014/10/26 职场文书
试用期工作表现自我评价
2015/03/06 职场文书
2015年度培训工作总结范文
2015/04/02 职场文书
关于Vue Router的10条高级技巧总结
2021/05/06 Vue.js
Python深度学习之实现卷积神经网络
2021/06/05 Python
基于angular实现树形二级表格
2021/10/16 Javascript
在Centos 8.0中安装Redis服务器的教程详解
2022/03/21 Redis
Windows 64位 安装 mysql 8.0.28 图文教程
2022/04/19 MySQL