【Web前端问题】请问函数参数声明是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=xlet声明没有任何关系。

  1. 变量声明
    let x或者var x是一个变量声明。
  2. 赋值表达式
    x=y是一个赋值表达式,包含=操作符,左识别符号x,右识别符y

  3. 赋值模式
    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的那一段,头大不想看

回答:

你可以这样理解:

  1. var x = 1;这个x是全局变量;
  2. 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的

以上是 【Web前端问题】请问函数参数声明是let声明的吗? 的全部内容, 来源链接: utcz.com/a/144176.html

回到顶部