关于js值传递和引用传递

关于函数传值

数据类型

  • 原始数据类型值 比如 Undefined, Null, Boolean, Number, String
  • 引用类型值 也就是对象类型,比如 Object, Array, Function, Date等。

不同类型在内存中的存储方式也不同

  • 原始数据类型的数据在内存中是存储在栈中的,因为原始数据类型所占的内存空间是固定可计算的;
  • 引用类型数据是可以拓展的,所以他们存放在堆中;返回的也并不是数据本身,而是数据在内存中的地址指针,然后计算机会把这个指针放到栈中,从而更快的读取数据。

举个栗子

不知道大家有没有这样试过,在变量传递的时候,对传递的形参进行类型转换,比如:

1
2
3
4
5
6
7
8
var para = 123;
function func(obj){
obj = 'abc';
}
func(para)
console.info(para)

可以先思考下,答案最后揭晓。
然后
下一题:

1
2
3
4
5
6
7
8
var para = {item: 123};
function func(obj){
obj.item = 'abc';
}
func(para)
console.info(para)

在接着,下一题:

1
2
3
4
5
6
7
8
9
10
var para1 = {item: 123};
var para2 = {item: 456};
function func(obj, obj2){
obj.item = 'abc';
obj2 = {item: 'abc'};
}
func(para1, para2)
console.info(para1, para2)

到这里,如果打印出来的和你想象的值是一样的,那么说明你已经能理解参数传递的概念了;
如果到这你晕了,那就看下面的分析;

先看第一个,
第一行

1
var para = 123;

这没太多说的,只是定义了一个变量,变量值是一个Number类型,也就是原始数据类型,
然后
定义了一个方法把这个变量传进去对他进行类型改变

1
2
3
function func(obj){
obj = 'abc';
}

按照人脑的思考模式;
参数被传递之后等于function拿到参数的执行权了
那么应该可以操作改变这个参数的内容,包括参数的类型(因为js是弱类型的语言,变量声明的时候没有指定类型,这是其他大部分语言不可进行的)

但是结果不是这样的
363F974C-9E02-4098-B7D1-2D94B81E1B0E.png

被传递的参数不仅类型不会改变,连内容都不会改变
FB2CAFE2-CDFA-46FA-A0B2-E7A3EC57B79F.png

后面两个其实是一个意思,
都是对象传递,
我们知道引用类型的变量存储的是内存地址,所以传递的也是内存地址,这里可能有个概念是 call by sharing 也就是这里实参传递给形参的并不是简单的引用传递,而是把引用的地址复制了一份,然后把这个副本传递了过去,所以不管是修改变量类型还是变量内容都是不会修改实参。

如果还是不太理解的话可以看下面的参考资料然后自己动手敲一敲,基本就能理解了。

参考资料

javascript传递参数如果是object的话,是按值传递还是按引用传递?
wiki - Evaluation strategy
Is JavaScript a pass-by-reference or pass-by-value language?