【JS】请问函数参数声明是let声明的吗?
var x = 1;
function foo(x = x) {
// ...
}
foo() // ReferenceError: x is not defined
上面代码中,参数x = x形成一个单独作用域。实际执行的是let x = x,由于暂时性死区的原因,这行代码会报错”x 未定义“。
以上是阮一峰老师的教程内容 http://es6.ruanyifeng.com/#do...
想请教一个问题,如果是let声明的话,那么为什么如果在函数体内用var重复声明变量x没有报错呢?
一旦设置了参数的默认值,函数进行声明初始化时,参数会形成一个单独的作用域(context)。等到初始化结束,这个作用域就会消失。这种语法行为,在不设置参数默认值时,是不会出现的。
如果是这个原因,那么为什么用let重复声明就会报错呢,毕竟是不同的作用域
-------------------分隔线-------------------
呃,非常感谢大家的回答,我理解什么是let的暂时性死区。。我不明白的是,为什么说函数参数是let声明的
回答
该解释的都解释差不多了,我只回答这个问题
为什么说函数参数是let声明的
function foo(x = x) {}
这里的x=x
跟let
声明没有任何关系。
- 变量声明
let x
或者var x
是一个变量声明。 - 赋值表达式
x=y
是一个赋值表达式,包含=
操作符,左识别符号x
,右识别符y
- 赋值模式
function foo(x=x){}
中的x=x
是一个函数声明
里的参数
里的赋值模式
。
最后,不要试图用js
去解释语法。想知道更多自己在线解析成ast
就知道了。astexplorer
想了很久,发现想错了,重新答一下。给 “上面代码中,参数x = x形成一个单独作用域。实际执行的是let x = x,由于暂时性死区的原因,这行代码会报错‘x 未定义’ 这句话带跑了。
函数里的声明并不是let。 tmd 经过楼主发的问题我才发现上面这句话是多么有问题
var x = 1;function foo(x = x) {
// ...
}
foo()
这里的报错不是因为let x = x;
是因为函数的提升优先级更高!相当于下面
function foo(x = x) {}
var x;
x = 1;
foo();
//Uncaught ReferenceError: x is not defined
所以
function foo(x = 1) {//这里的x=1只能相当于var x = 1才能解释得通。
let x = 2; // 这种情况会报错,因为重复声明
var x = 3; // 这种情况不会报错,如果参数x是let声明的话,那么用var重复声明应该报错吧?
}
提案
mdn
上面两个粗略看了一下没有说明题目中的这种情况
标准
这个是标准中关于函数如何执行的,按照道理说应该是有关于你疑问的解释的。
应该是最后面12.15.4的那一段,头大不想看
你可以这样理解:
- var x = 1;这个x是全局变量;
- function foo(x = x)相当于function foo(let x = x),这个 x 是只在函数体foo内生效的,它的作用域是函数foo。由于暂时性死区,let x = x,把x 赋值给 x的时候,其实x(也就是函数foo的x)根本都还没初始化完成,这个x 跟全局变量x是不同的,所以会报错。
补充一下:
请理解 一个概念 -- 变量提升:在代码运行前,函数声明和变量定义通常会被解释器移动到其所在作用域的最顶部
局部变量声明会提到所在函数的顶部,全局变量声明会提到所在代码块的顶部。
var x = 1;function foo() {
var x = x;
console.log(x); // 输出undefined
}
foo();
console.log(x); // 输出1
实际上这里定义的两个变量,一个是全局变量x一个是局部变量x。var x = x;这一句,实际上x的声明被提升到了函数的顶部,只是没有赋值而已,虽然有个全局变量x的值是1,但是局部变量会覆盖全局变量,所以是undefined。
var x = 1;function foo() {
let x = x; // 报错
console.log(x);
}
foo();
由于暂时性死区,其实函数foo内的 x 是不存在变量提升的,所以x根本还没声明,所以报错,这样会不会比较好理解
var x = 'outer value'
(function() {
// 这里会产生一个暂时性的死区
console.log(x) // 死区期间访问,产生ReferenceError错误
let x = 'inner value' // 对x的声明语句,这里死区结束
}())
由let/const声明的变量,当它们包含的词法环境(Lexical Environment)被实例化时会被创建,但只有在变量的词法绑定(LexicalBinding)已经被求值运算后,才能够被访问。
相当于你已经在函数内声明了x 但x没有被赋值前你是不能访问到x的
以上是 【JS】请问函数参数声明是let声明的吗? 的全部内容, 来源链接: utcz.com/a/83093.html