引用值误区和按值传递/按引用传递

引用值误区

我发现我一直错误的认为引用值就是被引用对象的指针地址。这导致我有很多地方没有明白。

定义:

原始值:最简单的数据。也就是简单数据类型(Number String Boolean undefined null Symbol(s6增加的))

引用值:由多个值构成的对象。也就是Object类型

1.string在java中是引用类型,而在javascript中却是原始值。

2.栈内存中存放的就是这些简单数据类型,外加上我之前错误理解的指针地址。

3.而堆内存中存储的就是对象。

4.由于这些原始值也就是原始类型占据的空间固定,所以放在栈这种较小空间里,而对象是可以一直变化的,大小不会固定。所以就放入堆内存中,但是指向该对象的指针地址却是固定的,所以储存在变量处的值(指向引用值的地址)也放在栈中。

5.要记得引用值不是引用的值,不是指针的值,而是和原始值对应的对象。

6.原始值不可以有属性,虽然添加不会报错,访问就会返回undefined,只用引用值可以动态添加属性。

7.原始类型初始化可以只使用字面量,也可以使用new创建对象实例,类似字面量,返回类型就不同了,一个原始类型,一个object,一个不可以添加属性,一个可以添加。

复制

原始值通过变量复制,在栈内存中会直接将原始值复制过去,两个变量独立,互不干扰。

引用值通过变量复制,就是将指针地址传过去,这两个变量现在同时指向该对象。一个对象发生变化,另外一个也会变化。

参数传递误区

js高级程序设计第四版85页讲了“ECMAScript中所有函数都是按值传递的”,这一块很容易造成误会,就如同我把引用值当成了引用地址。这里讲的意思是:

如果复制的是原始值,那么就和复制原始值变量一样;如果复制的是引用值,那么复制引用值就是复制引用值变量里边存储的地址。

上边说了引用值的变量也是保存在栈里边。

我们要明白一个概念,其实大的方向,我们可以分为按值传递和按引用传递的,但是按值传递其实还可以分为:按指针传递和按原始值传递

1.我们通过参数传递一个简单数据类型比如Number类型,用于加减,并不能对外边的Number改变。

2.我们通过指针传递,将一个对象当成实参传给新参,这个时候只是传递了这个对象在栈里边的指针地址(对象在堆里边的地址),我们可以访问到那个对象,并且可以修改那个对象的属性。但是我们修改这个形参的值,只是修改这个指向,无法再访问到该对象。对于形参操作,不会影响到实参。我改形参的值,只会指向新的地方,而实参本身没有任何改变,地址不会改变。

3.那么什么是按引用传递。我们创建一个对象,这个对象还是存在在堆里边,地址还是在栈里边,栈里边地址值还是在变量里边。如果是按引用传递形参相当于实参(对象)别名,我们不是在操作地址,再去找对象,而是直接操作对象,任何形参的变化都会反映到实参。在《js高级程序第四版》86页的例子里,作者要说的意思是,按引用传递传递的是引用关系,person和obj的引用关系,而不是person对象在栈里保存的间接地址,person和obj始终对应,obj重新new一个objerct,指向别处,由于person和object引用关系,person也必须随之改变指向别处,而不是就此obj和person就此失去联系。
4.所以要明白按指针传递是地址,我们操作地址并不会影响对象,我们还是通过地址操作对象,而按引用传递,就是将对象复制给形参,操作幸存就是操作对象,。

所以书中讲:很多开发者错误的认为,当在局部作用域中修改对象而发生改变反映到全局,就意味着参数是按引用的传递。

还有可能就是按指针传递,也就是按值传递。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值