理解函数传对象为什么是按值传递的而不是按引用传递的

一、基本类型的值与引用类型的值

基本类型的值:
Undefined Null Boolean Number String

基本类型的值存在栈内存中,是按值访问的,下面来看一个示例

var a = 10;
var b = a;
b = 20;
console.log(a) //打印结果 10 

那么为什么改变a对b没有影响呢?
答:b只是复制了a的一个副本,b的改变对a没有任何影响。下面借用其他的博主的一张图更能清晰的看明白:

![在这里插入图片描述](https://img-blog.csdnimg.cn/b5495258f55948abbe324f07d9a8cdf8.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5YmN56uv5a2m5LmgZmFt,size_15,color_FFFFFF,t_70,g_se,x_16

引用类型的值:
Object Array Date  Function等

引用类型是那些可能由多个值构成的对象。引用类型存在堆内存中,JavaScript 不允许直接访问内存中的位置,也就是说不能直接操作对象的内存空间,在操作对象时实际上在操作对象的引用(我理解的是指针),因为引用类型的值是按引用访问的,下面看一个列子。

//说一下这个过程 在我们new Object() 的时候 
//实际上是在堆内存中申请了一块内存来存放我们需要的东西
//然后obj1 其实存的是指针(执行我们那块内存的地址) 或者说引用
var obj1 = new Object() 
//上面我们已经说过了obj1 其实存放的是指针一个地址 那么obj2 = obj1 
//那么现在obj2 也存放了指向了我们创建那块内存的地址
var obj2 = obj1

obj2.name= '我是猪'

console.log(obj1.name) //我是猪
//相信这个打印结果你们都理解了 为什么我改obj2 为啥obj1 也变了。
//如果现在不理解那么你可能真的是 ’obj1.name‘

下面借用其他博主的一张图让你们更容易理解:在这里插入图片描述
好的理解了上面这些东西,我们再继续探讨为什么函数为什么都是按值传递的。其实现在聪明的小伙伴现在已经都明白了。

二、理解函数按值传递参数

传递基本类型的值
function addTen (num) {
		num+=10
  	return num
}
var count = 20;
var result = addTen(count)
console.log(count) //20
console.log(result) //30

相信大家这个应该很明白为啥,为啥count的值不是30呢?
答:1.我们创建一个函数,此函数接收一个num参数并+=10然后返回结果
2.接着声明一个变量count 值是20。
3.接着声明result 变量 调用函数传递count 其实看了上面的基本类型 我们这应该就能明白这里其实只是把count 的值传过去了 也就是20,然后参数num实际上是在函数内部声明一个num变量存放这个20,那么num在怎么加也不会改变count。

传递引用类型的值
function addTen (numObj) {
		numObj.num+=10
  	return numObj
}
var countObj = new Object()
countObj.num = 20
var resultObj = addTen(countObj)
console.log(countObj.num) //30
console.log(resultObj.num) //30

看的上面的这个例子我相信小伙伴应该也不会懵逼,因为我们前面在说引用类型的时候已经讲过为啥了,现在只是换一种方式。
答:1.我们创建一个函数,此函数接收一个numObj对象参数并把对象属性num+=10然后返回numObj
2.接着声明一个变量countObj对象里面有个num属性值是20。
3.接着声明resultObj对象调用函数方法并传递countObj(此时countObj是存放的是指向new Object()那块内存地址。)然后函数接收这个地址并存放在numObj 此时我们操作numObj 实际上就是在操作new Object()里面的num。那么numObj 把new Object()里面的num加了10,那么谁用这个地址访问num肯定都是30。

我说的”地址、指针“其实就是 ”引用“

三、下面看一个我前几天遇到群友发的一个面试题

var arr = [1,2,3]
function arrPush (arr){
  arr[3] = 4
  arr = [100]
}
console.log(arr) //1,2,3,4

看似一个很简单的题目其实有很多坑让你往里面跳,当时我看到我也跳进坑了。所以我又重新看了红宝书第三版的第四章变量、作用域和内存问题。之前看过只不过又给忘了。大家有什么好办法不忘记吗。其实我觉得就是我当时再看的时候就是为了看而看,而没有去认真思考,在这警惕各位小伙伴在学习知识的时候不要为了学而学,多问几个为什么,让自己深入理解。好了废话不多说我们来解答。
答:其实看了上面的例子再看这个题目已经很简单了,只是有几个迷惑你的地方。
1.首先声明一个arr数组里面放着123,一看数组我们知道是引用类型,存在堆内存中,然后arr其实是一个指针或者地址指向那块内存。
2.声明一个函数 函数接收一个参数 arr 此时不要搞混这个arr是函数的局部变量arr 而不是全局变量那个arr 。然后在arr[3]的位置放了一个4,然后arr又等于了[100]。
3.打印arr 此时打印的arr是全局变量的arr,函数里面第一步arr[3] = 4其实是全局变量arr存的地址指向[1,2,3]这块内存,然后我们根据这个地址在这块内存中的第三位放了一个4,紧接着arr = [100],函数内部arr本来存的是全局arr一个地址,现在直接给了它一个指向内存中存放[100]的一个地址、指针。相当于直接给他换了一个地址不再是传进来那个地址,其实并没有操作[1,2,3]这块内存,所以最外层打印的结果1234,迷惑的地方就是变量名跟参数名用了同意的名字 这会让很多小伙伴搞混。

简单的一个题涉及那么多的知识点,小伙伴们要加油啊。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值