JavaScript参数传递方式

这几天遇到js参数传递方式的问题,深切探究一番,将所得结果总结于此segmentfault

常见的几种传递方式

传值调用(call by value)

在传值调用中实际参数被求值,其值被绑定到函数中对应的变量上(一般是把值复制到新内存区域)。在函数返回后调用者做用域里的曾传给函数的任何东西都不会变。

传引用调用(call by reference)

在“传引用调用”求值中,传递给函数的是它的 实际参数的隐式引用(即实际参数的地址)而不是实参的拷贝。一般函数可以修改这些参数(好比赋值),并且改变对于调用者是可见的。

传共享对象调用(call by sharing)

在传共享对象调用中,传递给函数的是实参所指向引用对象的地址,而不是实参的地址,即传递共享对象。故在函数中修改引用对象时,实参的值也会跟着变化,而若是是从新给新参赋值后,再进行任何修改都不会影响到外面的实参了。

JS中的传值方式

Number--传值调用

let a = 1;
function add(val) {
  val += 1;
  console.log(`val=${val}`); // 2
}

add(a);
console.log(`a=${a}`); // 1

String--传值调用

let a = 'hahaha';
function change(val) {
  val = 'heiheihei';
  console.log(`val=${val}`); // heiheihei
}

change(a);
console.log(`a=${a}`); // hahaha

Boolean--传值调用

Symbol--传值调用

let a = Symbol('prop');
function change(val) {
  val = Symbol(2);
  console.log(`val=${val.toString()}`); // Symbol(2)
}

change(a);
console.log(`a=${a.toString()}`); // Symbol(prop)

null--传值调用

undefined--传值调用

Object--传共享对象调用

let obj = {
    a: 1
}
function change(obj) {
    obj.a = 2;
    console.log(obj); // {a: 2}
    obj = {
        a: 3
    }
    console.log(obj); // {a: 3}
}

change(obj);
console.log(obj); // {a: 2}

从上面的代码能够看出,在函数中对参数所指向的对象进行修改时会影响到外面的实参,但对函数参数从新赋值时,不会影响到实参,故js引用类型的传值方式为call by sharing函数

深刻探究

变量存储方式

图片描述

C#中类型有两种:值类型和引用类型,它们之间的却别在于实际数据存储的位置(如上图)。值类型的变量和实际数据都存储在堆栈中;而引用类型则只有变量存储在堆栈中,变量存储着实际数据的地址,实际数据存储在与地址相对应的托管堆中。学习

C#中的值传递

  • 正常状况下,值类型按值传递
  • 正常状况下,应用类型按共享对象的方式传递(call by sharing),但string类型除外(因为string的不可变性,它是按值传递的)
  • 经过使用ref或out关键字,值类型和引用类型均可以按引用传递

总结

综上所述(证实题2333),值传递和引用传递的参数类型既能够是值类型又能够是引用类型,可是call by sharing的参数类型只能是引用类型。spa

我的理解:JS中,null赋值的变量时对象,可是,变量指向的引用地址为空,故在函数中修改参数的值,对实参不会又任何影响,因此是按值传递。string类型应该跟C#按值传递的缘由一致。

参考:
维基百科
JS中的值是按值传递,仍是按引用传递呢
《Learning hard C#学习笔记》第10章code

相关文章
相关标签/搜索