博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
JavaScript参数按值传递的理解
阅读量:5772 次
发布时间:2019-06-18

本文共 1079 字,大约阅读时间需要 3 分钟。

看到一个这样的问题

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

按照一般的理解第二次重写name属性会覆盖原先的name,输出应该是"Greg"才对。

这个问题其实就是高程书上的原题,高程书的一些地方看了很多遍,但是每次重看都还是会有新的理解,这里理解的关键在于JavaScript函数的参数是按值传递的。
之前只是粗泛的了解参数按值传递,但是却并没有搞清楚本质,结合高程书和知乎的这个回答才对这个问题算是真正理解了。

栈内存与堆内存

简单类型的值,它们的值直接存储在变量访问的位置,这是因为这些简单类型占据的空间是固定的,所以可将他们存储在较小的内存区域 – 栈中。这样存储便于迅速查寻变量的值。每次复制都是一个单独的副本,之间相互独立

var num1 = 5; var num2 = num1;

图示

Alt text

引用类型的值存储在堆(heap)中的对象,也就是说,存储在变量处的值是一个指针(point),指向存储对象的内存地址。这是因为:引用值的大小会改变,所以不能把它放在栈中,否则会降低变量查寻的速度。相反,放在变量的栈空间中的值是该对象存储在堆中的地址。地址的大小是固定的,所以把它存储在栈中对变量性能无任何负面影响。

var obj1 = new Object(); var obj2 = obj1; obj1.name = "Nicholas"; alert(obj2.name); //"Nicholas"

图示

Alt text

ECMAScript中所有函数的参数都是按值来传递的

其实ECMAScript函数参数实际上是函数的局部变量,因此本题中将一个对象作为参数传入时,复制了一个指针指向对象在堆内存中的内存地址。按值复制传递上复制了一个指针变量,这个变量是按值传递的。

在调用函数内部将一个新的Object赋给obj之前内存情况是这样的:
Alt text
如果是按引用传递,就会直接把第一个(也就是变量本身)整个传递进去(就不会有第二格的存在了)
再将新的Object赋给obj之后:
Alt text
可以看到obj指向新的Object内存地址,而person引用的仍然是原来的Object,并且在函数内部新建的局部对象会在函数执行完毕后销毁,因此打印的name是第一个。

参考书籍

《JavaScript高级程序设计》

转载地址:http://dzoux.baihongyu.com/

你可能感兴趣的文章
Linux下的Memcache安装
查看>>
调用约定
查看>>
【转】ROS之topic和service通信比较
查看>>
[转]Linux 线程实现机制分析 Linux 线程实现机制分析 Linux 线程模型的比较:LinuxThreads 和 NPTL...
查看>>
lesson7:java线程池
查看>>
【2019年OCP新题】OCP题库更新出现大量新题-11
查看>>
N-Queens
查看>>
mysql允许远程连接
查看>>
PHP工厂模式的好处
查看>>
一道阿里笔试题
查看>>
【Android游戏开发之八】游戏中添加音频-详解MediaPlayer与SoundPoo!并讲解两者的区别和游戏中的用途!...
查看>>
Redis -- 数据类型小结
查看>>
数据库设计原则
查看>>
python3笔记<二> List
查看>>
ABP集成WIF实现单点登录
查看>>
模拟实现链栈
查看>>
条款9:绝不在构造和析构过程中调用virtual函数
查看>>
day8 socket编程CS模型完善错误处理
查看>>
Dzz任务板初版完成笔记-仿trello私有部署的一款轻量团队任务协作工具。
查看>>
线程基础8-quene讲解
查看>>