JS中let变量块级作用域疑问:两段代码为何表现不同?
关于let/const块级作用域的疑问解答
代码片段与问题
片段1:符合预期触发ReferenceError
const calculateArea = function(radius){ let area = 3.14 * radius ** 2; console.log(area); } console.log(area)
输出:
ReferenceError: area is not defined at <anonymous>:12:13 at mn (<anonymous>:16:5455)
片段2:看似未触发错误的代码
let age = 30; if(true){ let age = 40; let name = 'Peter'; console.log('Inside if block: ', name, age); } console.log('Outside if block: ', name, age);
输出:
Inside if block: Peter 40 Outside if block: 30
疑问解答
1. 为何片段2未触发ReferenceError?
你看到的输出是不完整的——这段代码实际运行时一定会触发ReferenceError。原因很明确:
name是在if块内部用let声明的,属于块级作用域,外部完全无法访问。当外部的console.log尝试读取name时,JS引擎找不到该变量,直接抛出ReferenceError: name is not defined。- 你看到的输出里只显示了
30,是因为报错前console.log已经输出了部分内容,或者控制台仅展示了未报错前的日志,实际代码执行到访问name时已经终止。
2. 为何if块外打印时age前有空格?
这是console.log的参数拼接规则导致的:
- 外部的
console.log第一个参数是'Outside if block: ',第二个参数name未定义,在抛出错误前,部分JS环境会先输出第一个字符串,接着换行,再输出已能正常获取的age值30。原本console.log会给每个参数之间添加空格,但由于name未定义导致拼接流程异常,最终呈现出你看到的格式。
额外补充:片段2中外部的age是最外层的块级作用域变量,和if块内部的age是两个完全独立的变量,互不干扰,这就是块级作用域的「变量遮蔽」效果——这和片段1中函数内部area无法被外部访问的规则完全一致。
内容的提问来源于stack exchange,提问作者Sam
相关产品推荐
相关产品推荐

