Javascript JS是否将参数列表视为可以关闭的范围?

Javascript JS是否将参数列表视为可以关闭的范围?,javascript,ecmascript-6,Javascript,Ecmascript 6,看看这个使用惰性表达式的简单代码: var x=1; 函数foo(x=2,f=()=>x){ var x=5; console.log(f()) } foo()函数参数具有相同的作用域,可以使用前面相邻的参数值设置后一个参数。函数参数具有作用域 在第一个示例中,您分配了一个新的x变量,这就是为什么它不会覆盖: //全局x var x=1; 函数foo(x=2/*局部作用域x*/,f=()=>x/*局部作用域x绑定到新函数作用域*/){ /*新的本地范围x。如果删除“var”,这将覆盖本地范围

看看这个使用惰性表达式的简单代码:

var x=1;
函数foo(x=2,f=()=>x){
var x=5;
console.log(f())
}

foo()
函数参数具有相同的作用域,可以使用前面相邻的参数值设置后一个参数。

函数参数具有作用域

在第一个示例中,您分配了一个新的
x
变量,这就是为什么它不会覆盖:

//全局x
var x=1;
函数foo(x=2/*局部作用域x*/,f=()=>x/*局部作用域x绑定到新函数作用域*/){
/*新的本地范围x。如果删除“var”,这将覆盖本地范围x*/
var x=5;
/*所有3个x都已访问*/
console.log(f(),x,window.x)
}

foo()
这是一个有趣的问题

最好参考Ecmascript 2017规范,以了解参数绑定机制的具体工作方式

定义一个函数时,有一个或两个函数在运行。根据参数是否具有默认值,环境记录设置的绑定会有所不同。如果参数具有默认值,则有2条环境记录正在运行。一个用于参数实例化,一个用于主体声明(如变量、内部函数等)

显然,当你喜欢的时候

function(x = 2, y = x){
  ...
}
在工作中有一个预分配功能,它必须有自己的上下文。如果是这样的话

function foo(x = 2, f = () => x) {
  var x = 5;
  console.log(f())
}
x
在定义函数参数时处于闭包状态

那么让我们看看它说什么

9.2.12函数声明安装(函数、参数列表)

为评估ECMAScript而建立执行上下文时 函数创建新的函数环境记录,并为其绑定 每个形式参数都在该环境记录中实例化。 函数体中的每个声明也被实例化。如果 函数的形式参数不包括任何默认值 初始值设定项,然后在同一文档中实例化主体声明 环境记录作为参数。如果是默认值参数 如果存在初始值设定项,则会为 机构声明。形式参数和函数初始化为 函数声明安装的一部分。所有其他绑定都是 在函数体求值期间初始化

此外,如果我们需要坐下来编写自己的JS引擎,我们还将详细介绍如何实现此功能的算法步骤27。a很有趣

27其他

a.注意,需要一个单独的环境记录,以确保由形式参数列表中的表达式创建的闭包不会 在函数体中具有声明的可见性


有趣。Babel当然会将其向下传输,以在函数体中移动声明,从而产生
5
,这将是一个bug。@NathanP。我知道这个例子不匹配。我指定了另一个例子我理解,而第一个(我不知道是否使用闭包)我不理解。什么是“惰性表达式”?第一个示例中的代码使用默认参数。删除
var
将打印
5
FWIW,如果在第一个示例中将
var x=5
更改为
let x=5
,则会出现错误,因为它已经声明过,因此要回答您的正式问题,否,参数列表没有自己的作用域。即使参数是一个直到以后才执行的函数?我对解释第二个示例不感兴趣。@CodingTrigue是。@RoyiNamir不确定你的意思?答案涉及第一个问题example@CodingIntrigue
函数foo(x=2,y=x*10,z=()=>x*y){var x=5;alert(z())}foo()
,另请参见,Typescript显示5。。。。不知道为什么。我也不明白为什么删除var会改变结果。X处于关闭状态并被捕获,那么为什么它会被覆盖呢?请从三个部分来考虑。您的窗口范围在顶部,中间的参数范围和底部的函数范围。从较高范围继承的变量将被较低范围的
var
取代,但如果不存在
var
声明,我们将沿着链向上移动,直到找到一个或点击
窗口。因此,在最低范围内添加变量声明只会影响在声明后使用该变量的方法。TypeScript将参数声明带入函数作用域,这解释了结果。如果它们有单独的作用域,那么我不明白为什么删除var会改变result@RoyiNamir如果您删除
var
,则
x
将指向在参数处声明的变量处的
x
,在这种情况下,您将使用
x=5对其重新赋值指令。因此
f
将打印
5
。如果在函数体中用
var
声明
x
,它将覆盖参数中定义的
x
,但函数将保留闭合值。当我们假设形式参数列表的范围包含函数体的范围时,使用
let
绑定(而不是
var
)声明
x
)会导致错误,这确实很奇怪。我想函数体没有建立块作用域,而是一种不同的作用域,这不会影响
let
绑定。@ftor这确实是一个很好的观点。它抛出一个
“x”已声明为
错误。我理解
let
的块作用域只允许函数体,这与参数级声明的作用域与默认值(同时具有相同标识符的两个变量)冲突。