按值传递(call by value)与按引用传递(call by reference)属于计算机学科中的求值策略(Evaluation Strategy),它决定了变量之间、函数调用时实参和形参之间值如何传递。
按值传递(call by value)
这是最常用的求值策略,函数的形参是被调用时所传实参的副本,修改形参的值并不会影响实参。
按引用传递(call by reference)
形参接受实参的隐式引用,而不是副本,这意味着,函数形参的值如果被修改,实参也会被修改,两者指向相同的储存区域。
按共享传递(call by sharing)
也叫按对象传递,按对象共享传递。该求值策略被用于Python、Java、Ruby、JS等多种语言。
对于传递到函数参数的对象类型,如果直接改变了拷贝的引用,那么不会影响原来的对象(这是按值传递的特性);如果是通过拷贝的引用,去进行内部的值的操作,那么就会影响原来的对象(这是按引用传递的特性)。
1 | function changeStuff(state1, state2) |
JavaScript值的传递方式
原始类型Primitive如Boolean/String/Number/Undefined/Symbol/BigInt,是按照值传递。
1 | var a = 1; |
虽然foo中传入a且在函数内部a被修改,但修改的是a的副本,外部的a值并没有被影响。
复杂类型Object对象,是按照共享传递的。在实际调用函数传递参数是,函数接受的是对象实参引用的副本。
1 | var obj = {x : 1}; |
函数内部对传入对象的内部进行了值的操作,此时呈现出“按引用传递”的特性。
1 | var obj = {x : 1}; |
函数内部对传入对象的整体进行了值的操作,此时呈现“按值传递”的特性。
可变与不可变
对象是可变的mutable,因此修改对象本身会影响到共享这个独享的引用和引用副本。
基本类型是不可变的immutable,按共享传递和按值传递没有任何区别,因此JavaScript基本类型符合按值传递和按共享传递。
由于基本类型都是不可变的,我们在JavaScript中对string进行操作,尝试“修改”字符串的内容,以为这样字符串就和原来不一样了。实际上,每一次在字符串上应用方法,返回的都是一个新的字符串,原来的字符串根本没变。
1 | > str = "abc"; |
对象是可变的,指向同一个对象的两个变量都可以修改同一个对象,它们共享同一个对象的引用,通过某一个变量修改对象的内容对另一个变量也有影响。但是某一个变量的指向更改后,并不会影响共享的对象。
1 | var obj = {x : 0}; |
参考
- 本文标题:JavaScript参数传递
- 本文作者:徐徐
- 创建时间:2021-04-04 20:10:06
- 本文链接:https://machacroissant.github.io/2021/04/04/js-func-parameter/
- 版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!