函数参数被修改会发生什么

这个问题在开发中比较常见,一个外部变量传递到函数内部,进行了修改,它到底会产生哪些变化?

先说结论,ECMAScript 中所有函数的参数都是按值传递的。这意味着函数外的值会被复制到函数内部的参数中,就像从一个变量复制到另一个变量一样。如果是原始值,那么就跟原始值变量的复制一样,如果是引用值,那么就跟引用值变量的复制一样。

下面,将对不同的场景做一些简要的说明。

基本类型

第一种情况,外部传入基本类型,函数内部去修改这个基本类型。

function basicFn(word) {
  word += ' world';
  return word;
}
const word = 'hello';
const result = basicFn(word);
console.log(word); // hello
console.log(result); // hello world

可以看到,内部并不能修改外面传入的值。由于函数接收的是传入值的一个副本,并且传入的是基本类型的值,所以副本肯定和传入值是不同的,那么在函数内部修改,不会影响外部数据的变化。

引用类型

第二种情况,传入一个引用类型的值会发生什么变化。

function refFunction(obj) {
  obj.name = 'Json';
  return obj;
}
const obj = {
  name: 'leevare',
};
const result = refFunction(obj);
console.log(obj); // { name: 'Json' }
console.log(result); // { name: 'Json' }

因为传入的数据为一个引用类型,那么传入的副本即使按照值传递,也不过是原始值的一个引用而已,在函数内部去修改副本对象,自然会影响到外部数据,所以上述示例两个对象输出的结果是一样的。

在函数中创建新的对象

如果在函数中整体把引用类型的入参赋值为一个新建对象会发生什么?

function refFunction(obj) {
  obj.name = 'Json';
  // 此处强行赋值为一个新对象
  obj = {
    name: 'new obj',
  };
  return obj;
}
const obj = {
  name: 'leevare',
};
const result = refFunction(obj);
console.log(obj); // { name: 'Json' }
console.log(result); // { name: 'new obj' }

咦,这次obj并没有变为在函数内部新建的对象,只是应用到了新建对象之前的修改。

这里印证了文章开头说的结论,函数的参数是其实是按照值传递的。如果是按照引用传递的话,里面改动势必会影响到外面,而此处并没有。究其原因,是因为当obj在函数内部被重写时,它变成了一个指向本地对象的指针,而这个本地对象在函数执行结束时就被销毁了,所以外部不能感知到内部新建的对象修改。

总结

以上几种场景在日常开发出现的频率还是比较高的,了解函数传参的方式,对于我们优化开发代码会带来一些帮助。

本文完。😊

如果您觉得本文对您有用,欢迎捐赠或留言~
微信支付
支付宝

发表评论

您的电子邮箱地址不会被公开。