传递参数的2种情况的理解。
最近差不多一个月没写博客了,主要的原因是目前在使用 Markdown 写学到的一些心得,一方面方便记笔记,另一方面页面排版更加的美观。
个人笔记站点 : https://yewenxiang23.github.io
碰到的问题:
今天碰到一个关于传递参数的问题,想了一下午,终于想通了,打算总结记录一下:
解决的思路:传参是值复制的一个过程,传递的是值,
1 function setName(obj){ 2 obj.name = "yewenxiang"; 3 obj = new Object(); 4 obj.name = "ye"; 5 } 6 var person = new Object(); 7 setName(person); 8 console.log(person.name); //yewenxiang
上面的代码输出了 "yewenxiang",而不是"ye"。感觉非常的怪异,下面来对于传递参数做一个总结。
传递参数:
- 所有的函数参数都是按值传递的
也就是说,把函数的值复制给函数内部的参数,就和把值从一个变量复制到另一个变量一样。
值有两种类型:
- 基本类型:值保存在栈内存中,复制的时候也是把值同时也复制了一份。
- 引用类型:值保存在堆内存中,栈内存中保存的只是指向堆内存中值的一个指针,复制的时候纸箱基本类型传参:
例子就拿 《javascript高级程序设计》上的例子来说
基本类型的值传参:
1 function addTen(num){ 2 num += 10; 3 return num; 4 } 5 var count = 20; 6 var result = addTen(count); 7 console.log(count); //20 8 console.log(result); //30
函数 addTen() 有一个num 参数,而参数实际上是函数的局部变量。在调用这个函数,并传入参数 count时。由于 count的值为20,传递参数的过程是一个值得复制过程,也就是把 count 的值20,复制给了参数(函数的局部变量) num = 20。在堆内存中存在了 count=20 和num=20,两个变量是互相不干扰的。
引用类型的值传参:
1 function setName(obj){ 2 obj.name = "yewenxiang"; 3 } 4 var person = new Object(); 5 setName(person); 6 console.log(person.name); //"yewenxiang"
这个例子中传入了一个 person 对象,也就是引用类型,引用类型的复制和基本类型的复制不同,复制的是栈内存 变量person 中保存的地址,这个地址也指向堆内存中同一个对象。所以修改了函数局部变量 obj的name属性为"yewenxiang" ,person.name也变为了"yewenxiang"。
证明参数是按值传递的一个例子:
1 function setName(obj){ 2 obj.name = "yewenxiang"; 3 obj = new Object(); 4 obj.name = "ye"; 5 } 6 var person = new Object(); 7 setName(person); 8 console.log(person.name);
这是我碰到的问题,开始我想的是输出 "ye" ,为什么会输出 "yewenxiang"呢。明明obj代表的是person这个对象,而函数内部赋值之后又重新构造了一个新对象并赋值为 "ye",所以应该输出 "ye"啊,为什么不是呢?那肯定是想错了嘛。废话少说 直接上图:
上面3.4行代码执行之前:
3.4行代码执行之后:
由于obj为函数的局部变量,那么我们如何证明呢?
1 function setName(obj){ 2 obj.name = "yewenxiang"; 3 console.log(obj.name); //yewenxiang 4 obj = new Object(); 5 obj.name = "ye"; 6 console.log(obj.name); //ye 7 } 8 var person = new Object(); 9 setName(person); 10 console.log(person.name); //yewenxiang 11 console.log(obj.name); //报错
这样就证明了我的想法是正确的。