JavaScript函数参数到底是按值传递还是引用传递?
摘自
发布日期:2021-05-20 10:07:09
浏览次数:42
分类:技术文章
本文共 2456 字,大约阅读时间需要 8 分钟。
1、传递参数
ECMAScript 中所有函数的参数都是按值传递
的。这意味着函数外的值会被复制到函数内部的参数
传参则只有按值传递
。 在按值传递参数时,值会被复制到一个局部变量(即一个命名参数,或者用 ECMAScript 的话说, 就是 arguments 对象中的一个槽位)。在按引用传递参数时,值在内存中的位置会被保存在一个局部变 量,这意味着对本地变量的修改会反映到函数外部。(这在 ECMAScript 中是不可能的。)来看下面这个 例子: ```jsfunction addTen(num) { num += 10; return num; } let count = 20;
let result = addTen(count); console.log(count); // 20,没有变化console.log(result); // 30
这里,函数 addTen()有一个参数 num,它其实是一个局部变量。在调用时,变量 count 作为参数
传入。count 的值是 20,这个值被复制到参数 num 以便在 addTen()内部使用。在函数内部,参数 num 的值被加上了 10,但这不会影响函数外部的原始变量 count。参数 num 和变量 count互不干扰
,它们 只不过碰巧保存了一样的值。如果 num 是按引用传递的,那么 count 的值也会被修改为 30。这个事实 在使用数值这样的原始值时是非常明显的
。但是,如果变量中传递的是对象,就没那么清楚了。比如, 再看这个例子: function setName(obj) { obj.name = "Nicholas"; } let person = new Object(); setName(person); console.log(person.name); // "Nicholas"
这一次,我们创建了一个对象并把它保存在变量 person 中。然后,这个对象被传给 setName()
方法,并被复制到参数 obj 中。在函数内部,obj 和 person 都指向同一个对象。结果就是,即使对象 是按值传进函数的,obj 也会通过引用访问对象。当函数内部给 obj 设置了 name 属性时,函数外部的 对象也会反映这个变化,因为 obj 指向的对象保存在全局作用域的堆内存上
。很多开发者错误地认为, 当在局部作用域中修改对象而变化反映到全局时,就意味着参数是按引用传递的。为证明对象是按值传 递的,我们再来看看下面这个修改后的例子: function setName(obj) { obj.name = "Nicholas"; obj = new Object(); obj.name = "Greg"; } let person = new Object(); setName(person); console.log(person.name); // "Nicholas"
这个例子前后唯一的变化就是 setName()中多了两行代码,将 obj 重新定义为一个有着不同 name
的新对象。当 person 传入 setName()时,其 name 属性被设置为"Nicholas"。然后变量 obj 被设置 为一个新对象且 name 属性被设置为"Greg"。如果 person 是按引用传递的,那么 person 应该自动将 指针改为指向 name 为"Greg"的对象。可是,当我们再次访问 person.name 时,它的值是"Nicholas", 这表明函数中参数的值改变之后,原始的引用仍然没变
。当 obj 在函数内部被重写时,它变成了一个指 向本地对象的指针。而那个本地对象在函数执行结束时就被销毁了
。 注意 ECMAScript 中函数的参数就是局部变量。 摘自《你不知道的JavaScript》
下面是例子
例子引用他人文章,这里我做个抛砖引玉之人,这个问题的确不是很好理解。
1、function test(m) { m = { v : 5}; } var m = { k : 30}; test(m); alert(m.v); // undefined2、
var obj = { value: 1};function foo(o) { o.value = 2; console.log(o.value); //2}foo(obj);console.log(obj.value) // 2
3、
var obj = { value: 1};function foo(o) { o = 2; console.log(o); //2}foo(obj);console.log(obj.value) // 1
如果 JavaScript 采用的是引用传递,外层的值也会被修改呐,这怎么又没被改呢?所以真的不是引用传递吗?
这就要讲到其实还有第三种传递方式,叫按共享传递。
而共享传递是指,在传递对象的时候,传递对象的引用的副本。
注意: 按引用传递是传递对象的引用,而按共享传递是传递对象的引用的副本!
所以修改 o.value,可以通过引用找到原值,但是直接修改 o,并不会修改原值。所以第二个和第三个例子其实都是按共享传递。
最后,你可以这样理解:
参数如果是基本类型是按值传递,如果是引用类型按共享传递。
但是因为拷贝副本也是一种值的拷贝,所以在高程中也直接认为是按值传递了。
所以,高程,谁叫你是红宝书嘞!
里面有很多讨论,建议还是看原文 附上转载地址:https://blog.csdn.net/weixin_45416217/article/details/115530715 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!
发表评论
最新留言
第一次来,支持一个
[***.219.124.196]2024年04月10日 08时42分44秒
关于作者
喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!
推荐文章
【Java面试题九】算法篇
2019-04-26
架构设计与分层
2019-04-26
【01】Java面试----基础方面的陷阱
2019-04-26
排序算法整合
2019-04-26
Java程序员常见笔试题分析
2019-04-26
Java笔试题
2019-04-26
Spring Boot快速入门---(一)spring boot的创建及几种启动方式
2019-04-26
【物联网实训项目】------(一)家庭智慧安防系统之前期项目工作准备
2019-04-26
【物联网实训项目】------(二)家庭智慧安防系统之定时监控
2019-04-26
【物联网实训项目】------(三)家庭智慧安防系统之实时监控
2019-04-26
【物联网实训项目】------(四)家庭智慧安防系统之智能温控
2019-04-26
【物联网实训项目】------(五)家庭智慧安防系统之智能监控
2019-04-26
【物联网实训项目】------(六)家庭智慧安防系统之智能监控
2019-04-26
【物联网实训项目】------(七)家庭智慧安防系统之人脸验证
2019-04-26
日常琐事(一)
2019-04-26
数据结构----绪论
2019-04-26