面试中关于 JavaScript 作用域的 5 个坑

焦点2025-11-05 09:49:40822

在 JavaScript 中,面试代码块、中关t作函数或模块为变量创建作用域。于J用域例如 if 代码块为变量 message 创建作用域:

if (true) {   const message = Hello;   console.log(message); // Hello } console.log(message); // throws ReferenceError 

在 if 代码块作用域内可以访问 message。面试但是中关t作在作用域之外,该变量不可访问。于J用域

以下是面试 5 种有趣的情况,其中 JavaScript 作用域的中关t作行为与你预期的不同。你可能会研究这些案例以提高对作用域的于J用域了解,或者只是面试为面试做准备。

1. for 循环内的中关t作 var 变量

思考以下代码片段:

const colors = [red, blue, white]; for (let i = 0, var l = colors.length; i < l; i++) {   console.log(colors[i]); // red, blue, white } console.log(l); // ??? console.log(i); // ??? 

当你打印 l 和 i 变量时会发生什么?

答案:

console.log(l) 输出数字 3 ,而 console.log(i) 则抛出 ReferenceError。于J用域

l 变量是面试使用 var 语句声明的。你可能已经知道,中关t作var 变量仅受函数体作用域限制而并非代码块。于J用域

相反,变量 i 使用 let 语句声明。因为 let 变量是块作用域的,所以 i 仅在 for 循环作用域内才可访问。

修复:

把 l 声明从 var l = colors.length 改为 const l = colors.length。现在变量 l 被封装在 for 循环体内。

2. 代码块中的站群服务器函数声明

在以下代码段中:

// ES2015 env {   function hello() {     return Hello!;   } } hello(); // ??? 

调用 hello() 会怎样?(代码段在 ES2015 环境中执行)

答案:

因为代码块为函数声明创建了作用域,所以在 ES2015 环境中调用 hello() 会引发 ReferenceError: hello is not defined。

有趣的是,在 ES2015 之前的环境中,在执行上述代码段时不会抛出错误。

3. 你可以在哪里导入模块?

你可以在代码块中导入模块吗?

if (true) {   import { myFunc } from myModule; // ???   myFunc(); } 

答案:

上面的脚本将触发错误:import and export may only appear at the top-level。

你只能在模块文件的最顶级作用域(也称为模块作用域)中导入模块。

修复:

始终从模块作用域导入模块。另外一个好的做法是将 import 语句放在源文件的开头:

import { myFunc } from myModule; if (true) {   myFunc(); } 

ES2015 的模块系统是静态的。通过分析 JavaScript 源代码而不是执行代码来确定模块的依赖关系。所以在代码块或函数中不能包含 import 语句,因为它们是在运行时执行的。

4. 函数参数作用域

思考以下函数:

let p = 1; function myFunc(pp = p + 1) {   return p; } myFunc(); // ??? 

调用 myFunc() 会发生什么?

答案:

当调用函数 myFunc() 时,将会引发错误:ReferenceError: Cannot access p before initialization。

发生这种情况是因为函数的参数具有自己的作用域(与函数作用域分开)。香港云服务器参数 p = p + 1 等效于 let p = p + 1。

让我们仔细看看 p = p + 1。

首先,定义变量 p。然后 JavaScript 尝试评估默认值表达式 p + 1,但此时绑定 p 已经创建但尚未初始化(不能访问外部作用域的变量 let p = 1)。因此抛出一个错误,即在初始化之前访问了 p。

修复:

为了解决这个问题,你可以重命名变量 let p = 1 ,也可以重命名功能参数 p = p + 1。

让我们选择重命名函数参数:

let p = 1; function myFunc(q = p + 1) {   return q; } myFunc(); // => 2 

函数参数从 p 重命名为 q。当调用 myFunc() 时,未指定参数,因此将参数 q 初始化为默认值 p + 1。为了评估 p +1,访问外部作用域的变量 p:p +1 = 1 + 1 = 2。

5. 函数声明与类声明

以下代码在代码块内定义了一个函数和一个类:

if (true) {   function greet() {     // function body   }   class Greeter {     // class body   } } greet();       // ??? new Greeter(); // ??? 

是否可以在块作用域之外访问 greet 和 Greeter?(考虑 ES2015 环境)

答案:

function 和 class 声明都是块作用域的。所以在代码块作用域外调用函数 greet() 和构造函数 new Greeter() 就会抛出 ReferenceError。

6. 总结

必须注意 var 变量,因为它们是函数作用域的,即使是在代码块中定义的。

由于 ES2015 模块系统是静态的免费信息发布网,因此你必须在模块作用域内使用 import 语法(以及 export)。

函数参数具有其作用域。设置默认参数值时,请确保默认表达式内的变量已经用值初始化。

在 ES2015 运行时环境中,函数和类声明是块作用域的。但是在 ES2015 之前的环境中,函数声明仅在函数作用域内。

希望这些陷阱能够帮你巩固作用域知识!

本文地址:http://www.bzve.cn/news/447c63398919.html
版权声明

本文仅代表作者观点,不代表本站立场。
本文系作者授权发表,未经许可,不得转载。

热门文章

全站热门

W10U盘台式重装系统教程(一步步教你如何使用W10U盘重新安装台式电脑系统)

锤子v3.2.7版本(突破性的技术和卓越的设计,为您带来无与伦比的手机体验)

探究天龙M40的性能和特点(解析天龙M40的设计和使用体验)

让你的苹果手机个性签名成为你的主题(个性签名创意灵感,让你的手机独一无二)

电脑挖矿机前景展望(数字货币热潮带来的机遇与挑战)

1080Ti海鹰显卡(探索海鹰怎样通过顶尖技术成为顶级显卡)

iOSbeta3(探索苹果iOSbeta3带来的性变化与升级)

金立S10相机的出色表现(一款优秀的摄影工具,细节无懈可击)

友情链接

滇ICP备2023006006号-39