资讯专栏INFORMATION COLUMN

call by sharing——JavaScript中“共享传参”和“按值传参”的理解

jsdt / 1612人阅读

摘要:众所周知,中参数是按值传递的。先大概介绍按值传参基本类型基本类型的参数传递比较简单,示例代码的值复制给了函数内部的局部变量所以在函数内部改变的值并不会影响外部的值。

众所周知,JavaScript中参数是按值传递的。与访问变量不同,基本类型和引用类型的参数在传递时都如同变量的复制。

但是我们在使用引用类型的参数传递时,经常会发现在函数内改变引用类型参数(如对象)会在函数外反映出来,这种情况貌似与“按值传参”的思想不符?
我本人在这个坑上也摔过很多次,最近遇到了一个新词:call by sharing(按共享传参)让我对这个问题有了比较深刻的认识。分享给对这个问题有误解的童鞋们。。。
先大概介绍按值传参

基本类型

基本类型的参数传递比较简单,示例代码

function add(num){
    num+=10;
    console.log(num);
}
var str=10;
add(str);//20
console.log(str);//10

str的值复制给了函数add内部的局部变量num,所以在函数内部改变num的值并不会影响外部str的值。

引用类型

红宝书上有这么一句话:在向参数传递引用类型的值时,会把这个值在内存中的地址复制给一个局部变量,因此这个局部变量的变化会反应函数外。

用两段代码来说明:

function setName1(obj){
    obj.name="Mike";
    return obj;
}
var person=new Object();
setName1(person);
console.log(person.name);//"Mike"

这段代码表面上看:函数内部的改变影响了函数外,难道是按引用传递?再看下面这段代码:

 function setName2(obj){
    obj.name="Mike";
    obj={name:"Tom"};
    return obj;
}
var person=new Object();
setName2(person);
console.log(person.name);//"Mike"

这个情况就比较有趣了,如果是按引用传递的,函数内函数外始终访问用一个引用,最后的结果应该是“Tom”才对。

再回到之前提到的:在向参数传递引用类型的值时,会把这个值在内存中的地址复制给一个局部变量,因此这个局部变量的变化会反应函数外。
其实这句话从另一个角度讲,就是call by sharing(共享传参)的定义。

先看一下ECMAScript中对call by sharing的定义

The main point of this strategy is that function receives the copy of the reference to object. This reference copy is associated with the formal parameter and is its value.
Regardless the fact that the concept of the reference in this case appears, this strategy should not be treated as call by reference (though, in this case the majority makes a mistake), because the value of the argument is not the direct alias, but the copy of the address.
The main difference consists that assignment of a new value to argument inside the function does not affect object outside (as it would be in case of call by reference). However, because formal parameter, having an address copy, gets access to the same object that is outside (i.e. the object from the outside completely was not copied as would be in case of call by value), changes of properties of local argument object — are reflected in the external object.
其实这段话,特别是标粗的地方说明的就是:引用类型把在内存中的地址复制给了函数中的局部变量。
所以出现会两种情况:

改变引用类型的属性
当在函数中改变引用类型(如对象)的属性时,是在同一个内存地址区域进行操作,所以会在函数外反映出来。如setName1

列表项目
在函数内,对形参进行了重新复制,即改变了形参的引用,(内存中的地址已经改变),与实参引用已经完全不一样了,所以不会对函数外引用类型变量参数产生影响,如setName2.

个人愚见,欢迎交流讨论。。。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/79538.html

相关文章

  • JavaScript 是如何工作JavaScript 共享传递值传

    摘要:它对数组和对象使用按值传递,但这是在的共享传参或拷贝的引用中使用的按值传参。例如在这里,变量和值在执行期间存储在堆栈中。返回值这是可选的,函数可以返回值,也可以不返回值。变量被推入堆栈,从而在执行时成为的副本。 这是专门探索 JavaScript 及其所构建的组件的系列文章的第 22 篇。 想阅读更多优质文章请猛戳GitHub博客,一年百来篇优质文章等着你! 如果你错过了前面的章节,可...

    keithyau 评论0 收藏0
  • JavaScript 是如何工作JavaScript 共享传递值传

    摘要:它对数组和对象使用按值传递,但这是在的共享传参或拷贝的引用中使用的按值传参。例如在这里,变量和值在执行期间存储在堆栈中。返回值这是可选的,函数可以返回值,也可以不返回值。变量被推入堆栈,从而在执行时成为的副本。 这是专门探索 JavaScript 及其所构建的组件的系列文章的第 22 篇。 想阅读更多优质文章请猛戳GitHub博客,一年百来篇优质文章等着你! 如果你错过了前面的章节,可...

    陈伟 评论0 收藏0
  • JavaScript 是传值调用还是传引用调用?

    摘要:所以传递给函数的值是这个值,所以函数执行结束原始变量并不会改变。传值调用在传值调用中,传递给函数参数是函数被调用时所传实参的拷贝。引用类型变量的值是一个指针,指向堆内存中的实际对象。所以传共享调用也可以说是传值调用。 1. 例子 先来看两个个来自于 《JavaScript 高级程序设计》P70-P71 的两个例子。 1.1. 基本类型参数传递 function addTen(num) ...

    darkbug 评论0 收藏0
  • 一个关于对象引用bug引发对于引用类型及数组简单思考

    摘要:图示如下而对于引用类型的复制可不是这样这个复制只是将的引用赋值给,二者是属于同一个引用,访问的都是堆内存中的同一个对象,任何一个该引用的变量发生变化,会对其余使用该引用的变量也发生变化。 这两天自己在写代码的时候,出现一个BUG,代码如下: class Car { constructor(carId) { this.position =...

    lijinke666 评论0 收藏0
  • [译] ES6 Arguments Parameters 用法解析

    摘要:默认参数有了我们不需要再去检测哪些值为并且给它们设定默认值了。我们甚至可以使用函数去找回默认参数的值注意这个函数只有在第二个参数省略时才会被调用。浏览器对默认参数的支持情况桌面浏览器移动端浏览器解构赋值解构赋值是的新特性。 原文地址:https://www.smashingmagazine.com/2016/07/how-to-use-arguments-and-parameters...

    msup 评论0 收藏0

发表评论

0条评论

jsdt

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<