如何理解js 函数作为参数传递的参数都是按值传递的

形参是函数声明和定义的时候跟的参数,实参是调用函数时传进去的参数。形参只是对参数进行类型说明,函数没有被调用时,形参不占用内存;只有在调用时,才会为形参分配内存,将实参传递进去,即用实参对形参进行初始化。
函数的参数传递有两种方式:值传递和引用传递。
值传递,就是函数调用时,给形参分配内存空间,利用实参对形参进行赋值。之后的执行过程中,形参和实参就脱离关系,互不影响。也就是说,用实参初始化形参之后,形参在子函数内如何变化,与实参无关。子函数返回或结束后,调用函数中的实参的值,并未因为赋值给形参,形参在子函数中改变而改变。
引用传递,就是利用引用类型的特点,来满足我们对于达到在被调函数中对形参的操作,等同于对实参的操作的效果的需要。引用是一种特殊类型的变量,实际上是另一个变量的别名,使用引用名和使用原来的变量名来访问变量是等效的。引用在做为形参时,不需要对其进行初始化,这是因为并不为形参分配内存。其他情况时,在声明引用变量时,要对其进行初始化,使它指向一个实际的对象。一旦引用被初始化之后,就不能指向其他对象。利用引用的特点,可以将形参设置为引用类型,这样函数调用时,实参对其进行初始化后,被调函数中任何对形参的操作,都相当于对调用函数中的实参的操作。
值调用和参数调用的区别,只在于函数声明和定义时,形参的写法不同,主调函数调用被调函数时的调用语句是一样的。
补充:读到拷贝构造函数一节时,对参数传递的两种方式有了新的理解:如果在子函数内部,形参的值不被修改,那么就可以采用值传递的方式;如果子函数内部,有对形参的修改操作,那么就必须采用引用传递方式来进行参数传递。
阅读(...) 评论()在 SegmentFault,学习技能、解决问题
每个月,我们帮助 1000 万的开发者解决各种各样的技术问题。并助力他们在技术能力、职业生涯、影响力上获得提升。
问题对人有帮助,内容完整,我也想知道答案
问题没有实际价值,缺少关键内容,没有改进余地
如何理解js高级书中的“ECMAScript中所有函数的参数都是按值传递的”这句话?
所有的函数参数传递都是值传递吗?那么引用传递呢?
如果函数参数是一个对象的话呢?
答案对人有帮助,有参考价值
答案没帮助,是错误的答案,答非所问
书里好像都说了吧,即使是引用类型,也还是按值传播。
同步到新浪微博
分享到微博?
关闭理由:
删除理由:
忽略理由:
推广(招聘、广告、SEO 等)方面的内容
与已有问题重复(请编辑该提问指向已有相同问题)
答非所问,不符合答题要求
宜作评论而非答案
带有人身攻击、辱骂、仇恨等违反条款的内容
无法获得确切结果的问题
非开发直接相关的问题
非技术提问的讨论型问题
其他原因(请补充说明)
我要该,理由是:
在 SegmentFault,学习技能、解决问题
每个月,我们帮助 1000 万的开发者解决各种各样的技术问题。并助力他们在技术能力、职业生涯、影响力上获得提升。C语言中,数组做函数参数如何才能按值传递?_百度知道
C语言中,数组做函数参数如何才能按值传递?
一直以为C默认func(type array[])是按值传递的?难道每次都得自行创建副本吗,今天才发现C和C++都是默认按地址传递。可是如何按值传递呢
我有更好的答案
1、数组做参数,完全无法按值传递。这是由C/C++函数的实现机制决定的。2、传数组给一个函数,数组类型自动转换为指针类型,因而传的实际是地址。下面三种函数声明完全等同:void func(int array[10])void func(int array[])void func(int *array)
采纳率:70%
来自团队:
void func(int array[10])void func(int array[])void func(int *array)所以以上三种函数声明完全等同;C++函数的实现机制决定的,数组类型自动转换为指针类型?当要在一个函数内使用一个数组时,数组做参数,因而传的实际是地址。下一个问题是:为什么偏要按值传递呢。实际情况是?只要能访问到我们所要的数据并对其进行操作,何苦钻牛角尖传数组给一个函数,完全无法按值传递。这是由C&#47,传一个指针进去不就行了
本回答被提问者和网友采纳
然后将数组名传递进去给函数就行!具体的可以看一下书!在函数中对其的访问也是和数组的操作类似数组其实就是指针的退化,数组名其实就是一个指针。就直接按指针做函数的参数就好
数组给一个函数,常用的是可把数组的首地址传给函数。即相当于是指针的应用 fun(int array[10][]) fun(int array[]) fun(int *array)三种调用方法
不可能按值传递的,设想一下type *arr =。。。。。sizeof(arr)为100万了字节,如果按照值传递,就要创建一个临时变量temp也为100万个字节,效率岂不是太低了。再可能arr是堆内存,参数传递是要属性相同,值相同,难道系统自行去new一段内存,这该用户去释放 还是系统自动回收呢?
其他2条回答
为您推荐:
其他类似问题
您可能关注的内容
c语言的相关知识
换一换
回答问题,赢新手礼包
个人、企业类
违法有害信息,请在下方选择后提交
色情、暴力
我们会通过消息、邮箱等方式尽快将举报结果通知您。& & & 我们把命名参数(arguments)视为局部变量,在向参数传递基本类型值时,如同基本类型变量的复制一样,传递一个副本,参数在函数内部的改变不会影响外部的基本类型值。如:
1 function add10(num){
2 num += 10 ;
5 var count = 10 ;
6 var result = add10(count);
7 alert(count);// 10
8 alert(result); //20
& & 在向参数传递引用类型的值时,会把这个值 在内存中的地址复制给一个局部变量,因此这个局部变量的变化会反映子啊函数的外部,例如:
function addName(obj){
obj.name = "Jewl";
var someBody = new object();
addName(someBody);
console.log(someBody.name);
这个例子其实是很让人困扰的,因为它更像按引用传递,说到传递方式,一般分为两种:
1.按值传递(call by value):函数的形参是被调用时所传实参的副本。修改形参的值并不会影响实参。
2.按引用传递(call by reference):函数的形参接收实参的隐式引用,而不再是副本。这意味着函数形参的值如果被修改,实参也会被修改。同时两者指向相同的值。
为了证明引用类型也是按值传递的,我们可以看看下面一个例子:
function addName(obj){
obj.name = "Jewl';
obj = new object();
obj.name = "Kancy";
var someBody = new object();
addName(someBody);
console.log(someBody.name)
与前面一个例子的区别是,本例将一个新对象赋值给形参,如果是按引用传递,那么someBody的name也会随之改变,显然不是。在函数内部给obj赋值时,这个变量引用就变成了一个局部变量,在函数执行完就会被销毁。
  为了加深理解,我会再来看看js中引用类型值的存储,在js中,引用类型值是保存在内存中的对象,JavaScript不允许直接访问内存中的位置,也即不能直接操作对象的内存空间,在操作对象时,实际上是操作对象的引用而不是实际的对象。引用类型的值是按引用访问的。因此改变其中一个变量,就会影响另外一个变量。
var obj1 = new Object(); var obj3 = new Object();var obj2 = obj1;obj1.name = "Jewl";obj3.name = "Kancy";console.log(obj1.name);
//"Jewl"console.log(obj2.name);
//"Jewl"obj1 = obj3;console.log(obj1.name);
//"Kancy"console.log(obj2.name);
//"jewl"console.log(obj3.name);
当我们把obj1赋值为obj3时,obj1指向和obj3相同的对象,obj2依然指向之前的对象。由此可以看出传参过程和此处类似,但不属于按引用传参,所以讲JavaScript里参数传递均归为按值传递。
JavaScript新手,第一次发文,请多指教。
阅读(...) 评论()函数参数的传递三种方式
我的图书馆
函数参数的传递三种方式
一. 三道考题开讲之前,我先请你做三道题目。(嘿嘿,得先把你的头脑搞昏才行……唉呀,谁扔我鸡蛋?)1. 考题一:程序代码如下:void Exchg1(int x, int y)&&{&&&&tmp=x;&&x=y;&&y=&&printf(“x=%d,y=%d\n”,x,y)}void main(){&&int a=4,b=6;&&Exchg1 (a,b) ;&&printf(“a=%d,b=%d\n”,a,b)}输出的结果:x=____, y=____a=____, b=____问下划线的部分应是什么,请完成。2. 考题二:代码如下。Exchg2(int *px, int *py){&&int tmp=*&&*px=*&&&*py=&&print(“*px=%d,*py=%d\n”,*px,*py);}main(){&&int a=4;&&int b=6;&&&&&&Exchg2(&a,&b);&&&&&&Print(“a=%d,b=%d\n”, a, b);}输出的结果为:*px=____, *py=____a=____, b=____问下划线的部分应是什么,请完成。3. 考题三:Exchg2(int &x, int &y){&&&int tmp=x;&&&x=y;&&&y=&&print(“x=%d,y=%d\n”,x,y);}main(){&&int a=4;&&int b=6;&&&&&&Exchg2(a,b);&&&&&&Print(“a=%d,b=%d\n”, a, b);}输出的结果:x=____, y=____a=____, b=____&&&&问下划线的部分输出的应是什么,请完成。&&&&你不在机子上试,能作出来吗?你对你写出的答案有多大的把握?&&&&正确的答案,想知道吗?(呵呵,让我慢慢地告诉你吧!)&&&&好,废话少说,继续我们的探索之旅了。&&&我们都知道:C语言中函数参数的传递有:值传递,地址传递,引用传递这三种形式。题一为值传递,题二为地址传递,题三为引用传递。不过,正是这几种参数传递的形式,曾把我给搞得晕头转向。我相信也有很多人与我有同感吧?下面请让我逐个地谈谈这三种传递形式。二. 函数参数传递方式之一:值传递1. 值传递的一个错误认识&&&&先看题一中Exchg1函数的定义:void Exchg1(int x, int y)&&&//定义中的x,y变量被称为Exchg1函数的形式参数{&&&&tmp=x;&&x=y;&&y=&&printf(“x=%d,y=%d\n”,x,y)}问:你认为这个函数是在做什么呀?答:好像是对参数x,y的值对调吧?&&&&请往下看,我想利用这个函数来完成对a,b两个变量值的对调,程序如下:void main(){&&int a=4,b=6;&&Exchg1 (a,b)&&&&&//a,b变量为Exchg1函数的实际参数。/&&printf(“a=%d,b=%d\n”,a,b)}&&&&我问:Exchg1 ()里头的&&printf(“x=%d,y=%d\n”,x,y)语句会输出什么啊?&&&&我再问:Exchg1 ()后的&&printf(“a=%d,b=%d\n”,a,b)语句输出的是什么?&&&&程序输出的结果是:x=6 , y=4&&a=4 , b=6&&//为什么不是a=6,b=4呢?&&&&奇怪,明明我把a,b分别代入了x,y中,并在函数里完成了两个变量值的交换,为什么a,b变量值还是没有交换(仍然是a==4,b==6,而不是a==6,b==4)?如果你也会有这个疑问,那是因为你跟本就不知实参a,b与形参x,y的关系了。2. 一个预备的常识为了说明这个问题,我先给出一个代码:int a=4;x=a;x=x+3;&&&&看好了没,现在我问你:最终a值是多少,x值是多少?&&&&(怎么搞的,给我这个小儿科的问题。还不简单,不就是a==4&&x==7嘛!)&&&&在这个代码中,你要明白一个东西:虽然a值赋给了x,但是a变量并不是x变量哦。我们对x任何的修改,都不会改变a变量。呵呵!虽然简单,并且一看就理所当然,不过可是一个很重要的认识喔。3. 理解值传递的形式看调用Exch1函数的代码:main(){&&int a=4,b=6;&&Exchg1(a,b) //这里调用了Exchg1函数&&&&&&&&&&printf(“a=%d,b=%d”,a,b)}Exchg1(a,b)时所完成的操作代码如下所示。int x=a;//←int y=b;//←注意这里,头两行是调用函数时的隐含操作tmp=x;x=y;y=&&&&请注意在调用执行Exchg1函数的操作中我人为地加上了头两句:int x=a;int y=b;&&&&这是调用函数时的两个隐含动作。它确实存在,现在我只不过把它显式地写了出来而已。问题一下就清晰起来啦。(看到这里,现在你认为函数里面交换操作的是a,b变量或者只是x,y变量呢?)&&&&原来 ,其实函数在调用时是隐含地把实参a,b 的值分别赋值给了x,y,之后在你写的Exchg1函数体内再也没有对a,b进行任何的操作了。交换的只是x,y变量。并不是a,b。当然a,b的值没有改变啦!函数只是把a,b的值通过赋值传递给了x,y,函数里头操作的只是x,y的值并不是a,b的值。这就是所谓的参数的值传递了。&&&&哈哈,终于明白了,正是因为它隐含了那两个的赋值操作,才让我们产生了前述的迷惑(以为a,b已经代替了x,y,对x,y的操作就是对a,b的操作了,这是一个错误的观点啊!)。
作者:&&&&& 发表时间: 11:48:00
三. 函数参数传递方式之二:地址传递继续——地址传递的问题!看题二的代码:Exchg2(int *px, int *py){&&int tmp=*&&*px=*&&*py=&&print(“*px=%d,*py=%d\n”,*px,*py);}main(){&&int a=4;&&int b=6;&&&&&&Exchg2(&a,&b);&&&&&&Print(“a=%d,b=%d\n”, a, b);}它的输出结果是:&&*px=6,*py=4&&a=6,b=4&&&&看函数的接口部分:Exchg2(int *px,int *py),请注意:参数px,py都是指针。&&&&再看调用处:Exchg2(&a, &b);&&&&它将a的地址(&a)代入到px,b的地址(&b)代入到py。同上面的值传递一样,函数调用时作了两个隐含的操作:将&a,&b的值赋值给了px,py。px=&a;py=&b;&&&&呵呵!我们发现,其实它与值传递并没有什么不同,只不过这里是将a,b的地址值传递给了px,py,而不是传递的a,b的内容,而(请好好地在比较比较啦)&&&&整个Exchg2函数调用是如下执行的: &&px=&a;&&&//&&py=&b;&&&//请注意这两行,它是调用Exchg2的隐含动作。&&int tmp=*&&*px=*&&*py=&&print(“*px=%d,*py=%d\n”,*px,*py);&&&&这样,有了头两行的隐含赋值操作。我们现在已经可以看出,指针px,py的值已经分别是a,b变量的地址值了。接下来,对*px,*py的操作当然也就是对a,b变量本身的操作了。所以函数里头的交换就是对a,b值的交换了,这就是所谓的地址传递(传递a,b的地址给了px,py),你现在明白了吗?四. 函数参数传递方式之三:引用传递&&&&看题三的代码:Exchg3(int &x, int &y) //注意定义处的形式参数的格式与值传递不同{&&&int tmp=x;&&&x=y;&&&y=&&print(“x=%d,y=%d\n”,x,y);}main(){&&int a=4;&&int b=6;&&&&&&Exchg3(a,b);&&//注意:这里调用方式与值传递一样&&&&&&Print(“a=%d,b=%d\n”, a, b);}输出结果:x=6, y=4a=6, b=4&&&//这个输出结果与值传递不同。&&&&看到没有,与值传递相比,代码格式上只有一处是不同的,即在定义处:Exchg3(int &x, int &y)。&&&&但是我们发现a与b的值发生了对调。这说明了Exchg3(a,b)里头修改的是a,b变量,而不只是修改x,y了。&&&&我们先看Exchg3函数的定义处Exchg3(int &x,int &y)。参数x,y是int的变量,调用时我们可以像值传递(如: Exchg1(a,b); )一样调用函数(如: Exchg3(a,b); )。但是x,y前都有一个取地址符号&。有了这个,调用Exchg3时函数会将a,b 分别代替了x,y了,我们称x,y分别引用了a,b变量。这样函数里头操作的其实就是实参a,b本身了,也就是说函数里是可以直接修改到a,b的值了。&&&最后对值传递与引用传递作一个比较:1. 在函数定义格式上有不同:值传递在定义处是:Exchg1(int x, int y);引用传递在这义处是:Exchg1(int &x, int &y);2. 调用时有相同的格式:值传递:Exchg1(a,b);引用传递:Exchg3(a,b);3. 功能上是不同的:值传递的函数里操作的不是a,b变量本身,只是将a,b值赋给了x,y函数里操作的只是x,y变量而不是a,b,显示a,b的值不会被Exchg1函数所修改。引用传递Exchg3(a,b)函数里是用a,b分别代替了x,y。函数里操作的就是a,b变量的本身,因此a,b的值可在函数里被修改的。
TA的最新馆藏
喜欢该文的人也喜欢

我要回帖

更多关于 c语言函数参数传递 的文章

 

随机推荐