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 相关文章推荐
非常漂亮的JS代码经典广告
Oct 21 Javascript
面向对象的Javascript之二(接口实现介绍)
Jan 27 Javascript
jQuery extend 的简单实例
Sep 18 Javascript
jQuery选择id属性带有点符号元素的方法
Mar 17 Javascript
浅谈jQuery中的checkbox问题
Aug 10 Javascript
微信小程序 教程之WXML
Oct 18 Javascript
javascript实现鼠标点击页面 移动DIV
Dec 02 Javascript
jQuery中map函数的两种方式
Apr 07 jQuery
Bootstrap Table使用整理(四)之工具栏
Jun 09 Javascript
解决vue中post方式提交数据后台无法接收的问题
Aug 11 Javascript
使用koa2创建web项目的方法步骤
Mar 12 Javascript
自定义javascript验证框架示例【附源码下载】
May 31 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读取文件内容至字符串中,同时去除换行、空行、行首行尾空格(Zjmainstay原创)
2012/07/31 PHP
thinkphp的c方法使用示例
2014/02/24 PHP
php使用str_shuffle()函数生成随机字符串的方法分析
2017/02/17 PHP
php如何获取Http请求
2020/04/30 PHP
模仿JQuery.extend函数扩展自己对象的js代码
2009/12/09 Javascript
js解决弹窗问题实现班级跳转DIV示例
2014/01/06 Javascript
JS的事件绑定深入认识
2014/06/26 Javascript
JavaScript数据结构之二叉查找树的定义与表示方法
2017/04/12 Javascript
Vue form 表单提交+ajax异步请求+分页效果
2017/04/22 Javascript
浅谈vue-router2路由参数注意的问题
2017/11/08 Javascript
angularjs 的数据绑定实现原理
2018/07/02 Javascript
发布一款npm包帮助理解npm的使用
2019/01/03 Javascript
python实现绘制树枝简单示例
2014/07/24 Python
深入理解Python 代码优化详解
2014/10/27 Python
Python中操作符重载用法分析
2016/04/29 Python
python实现数据图表
2017/07/29 Python
django允许外部访问的实例讲解
2018/05/14 Python
python实现flappy bird游戏
2018/12/24 Python
django 实现编写控制登录和访问权限控制的中间件方法
2019/01/15 Python
Python基础之文件读取的讲解
2019/02/16 Python
Python中使用__new__实现单例模式并解析
2019/06/25 Python
详解Python 实现 ZeroMQ 的三种基本工作模式
2020/03/24 Python
python实现处理mysql结果输出方式
2020/04/09 Python
英语专业毕业生求职简历的自我评价
2013/10/24 职场文书
销售部主管岗位职责
2013/12/18 职场文书
初一体育教学反思
2014/01/29 职场文书
阳光体育活动方案
2014/02/16 职场文书
《会走路的树》教后反思
2014/04/19 职场文书
考生诚信考试承诺书
2014/05/23 职场文书
体现团队精神的口号
2014/06/06 职场文书
大专学生求职自荐信
2014/07/06 职场文书
使用Redis实现秒杀功能的简单方法
2021/05/08 Redis
利用python调用摄像头的实例分析
2021/06/07 Python
Redis主从配置和底层实现原理解析(实战记录)
2021/06/30 Redis
解析python中的jsonpath 提取器
2022/01/18 Python
docker compose 部署 golang 的 Athens 私有代理问题
2022/04/28 Servers