阅读 87

函数的形参是 var声名 还是 let声名 ?

最近看 阮一峰老师ES6入门教程 中对 暂时性死区有如下理解:

// 有些“死区”比较隐蔽,不太容易发现: function bar(x = y, y = 2) {   return [x, y]; } bar(); // Cannot access 'y' before initialization /* 上面代码中,调用`bar`函数之所以报错(某些实现可能不报错), 是因为参数`x`默认值等于另一个参数`y`, 而此时`y`还没有声明,属于“死区”。如果`y`的默认值是`x`,就不会报错,因为此时`x`已经声明了。*/ 复制代码

如果说函数形参声名存在暂时性死区,

那么此处 y 应该为 let 声名,

然而我们可以在函数内部使用 var 进行声名 :

function bar(x) {     var x = 3;     console.log(x); } bar(2);  // 3 复制代码

按正常情况来说, 如果用 let 声名过的变量,是无法再用 var 声名的:

let x = 2; var x = 3; console.log(x); // 'x' has already been declared 复制代码

有的同学说 function() 括号中的部分属于一个 块级作用域

如果这样的话应该 类似 for()循环的 let 声名

然而 :

1. for 循环中

for (let i = 0; i < 3; i++) {   let i = 'abc';  // 此处并不会报错   console.log(i); } // 'abc' // 'abc' // 'abc' 复制代码

2. 函数中

function bar(x) {     let x = 3;     console.log(x); } bar(2); // Identifier 'x' has already been declared 复制代码

可见这样理解并不合理

--------------------------------------------------------------------------

在大佬指出 :

js中,执行一个函数时,形参和局部变量是存在一个活动对象里的,或者叫变量对象,

如果在局部变量中定义了一个和形参相同名字的变量,编译器会忽略这个定义,

而所有对该变量的操作都会反映到形参的那个变量中去

function fn(id) {     console.log(id); // 2     var id = 9;     return arguments[0] } console.log(fn(2)); // 9 复制代码

我理解为:

  1. 在函数内部不定义与形参相同名字相同的变量时,形参采取 let 声名,

  2. 然而如果在函数内部定义与形参相同名字的变量,let 声名会被忽略,进而将所有操作指向函数内部定义的同名变量,这个过程也存在实参赋值形参的过程,即 id = 2; 可以理解成如下

id = 2; var id = 9; return id 复制代码

此处 var 关键字进行变量提升也并不会影响结果,因为在全局作用域下该部分输出也是没问题的,

这也是 let 声名 id 会报错的原因了,因为在 let 声名之前我们已经执行了 id = 2;

---------------------------------------------------------------------------------------

感谢大佬的指正,这里用大佬原话解释:

  1. 形参既不是var也不是let声明,它本身就是函数参数声明,是一种独立的类型

  1. 另外函数的括号是函数作用域,也不是块级作用域,和块级作用域是有区别的。

---------------------------------------------------------------------------------------

总结:

综合阮大的观点,个人理解为:

  1. 第一段代码确实存在暂时性死区,但并不是 let 引起的,而是函数形参默认声名引起的

  1. 函数内部重新定义形参会导致对形参的所有操作转移到同名参数上(因为 arguement 会发生变化)

  1. 而实参赋值形参的操作仍然会在函数执行后立即执行,这就对 为什么可以使用 var 重新声名 而不能使用 let 做出了合理的解释


作者:早川秋
链接:https://juejin.cn/post/7026337395964379172


文章分类
代码人生
版权声明:本站是系统测试站点,无实际运营。本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 XXXXXXo@163.com 举报,一经查实,本站将立刻删除。
相关推荐