【前端开发】js函数形参与函数内声明的参数同名问题

本文探讨了JavaScript中函数形参与局部变量同名时的处理机制,包括ES5和ES6中的变量提升以及默认值形参导致的作用域差异。建议避免在函数体中使用var声明形参同名变量以防止潜在问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在使用js函数的过程中,有时可能会遇到函数的形参和函数体内局部声明的变量相同的情况,自己也可能无意间声明了同名的局部变量。变量同名时js到底是怎么处理的呢,下面探寻下背后的原理。

ES5中变量声明

有关变量声明的问题,在ES5中有如下代码:


console.log(value); // undefined

var value = 10;
var value;

console.log(value); // 10

可能大家看到上述代码会认为第一行会报错,因为输出value的时候value并没有定义,会抛出一个ReferenceError错误,其实不然。

在js代码的执行时候不完全是一行一行的执行,在有var声明变量的时候,会在编译阶段把var声明的变量提升,把变量赋值保留在原来的位置,上述代码会首先被转成如下代码:


var value;
var value;

console.log(value); // undefined
value = 10;
console.log(value); // 10

变量声明提升之后,在真正的执行的时候如果遇到变量已经声明之后,再次重复声明会被忽略,第二个var value不起作用。所以代码运行之后第一个console.log会输出undefined,第二个console.log会输出10。

ES5中函数形参同名变量

在ES5中允许使用var声明形参同名变量,函数用var声明的变量同样遵循变量提升原则


function func(value) {
  console.log(value); // 10
  var value;
  console.log(value); // 10
}

func(10)

上述代码中由于变量已经在形参中声明,并且执行的时候已经赋值10,所以两个console.log都会输出10。

ES6中函数形参同名变量

在ES6中,如果函数中出现与形参同名的变量有两种情况,形参与ES5定义一样的情况和形参有默认值、rest参数等的情况。如果形参局部变量定义与ES5的方式相同,那么执行结果与上面讨论的并无不同。以下详细介绍下ES6中函数含有默认值形参的情况,有如下代码:


function func(value = 10) {
  var value = 20;
  
  console.log(value); // 20
}

func();

;

上面的实例大家可能一眼就看出console.log会输出20,会认为形参的value和局部变量的value是同一个变量。其实事情没有那么简单,形参的value和局部参数的value并不是同一个变量,它们分别在不在一个作用域,形参定义为一个作用域,局部变量的定义属于另外一个全新的块级作用域,可以从chrome浏览器debug模式下查看不同的作用域(Scope)

图片

看了以上的例子就很容易看出来以下代码执行console.log会输出20而不是10了


function func(
  value = 0,
  setValue = () => { value = 10 }
) {
  var value = 20;
  setValue();
  console.log(value); // 20
}

func();

为什么含有默认值的形参和同名的var变量会属于不同的作用域?

因为在ES5中形参和同名var变量是同一个值,在ES6中这种写法仍然正确,但是含有默认值的形参是用let定义,如果使用var定义的同名变量仍属同一个作用域会导致SyntaxError错误(变量重复声明),为了解决这个问题设置了不同的作用域。

通过以上剖析,建议尽量不要在函数体中用var声明形参同名变量,这样会导致一些意想不到的问题,会给程序的正常运行埋下隐患。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值