Products
GG网络技术分享 2025-03-18 16:13 70
作者:疯狂的技术宅
转发链接:https://mp.weixin.qq.com/s/XkEvgyhJ8S0xQS2kOY67Qw
在 JavaScript 中,代码块、函数或模块为变量创建作用域。例如 if 代码块为变量 message创建作用域:
1if(true){
2constmessage='Hello';
3console.log(message);//'Hello'
4}
5console.log(message);//throwsReferenceError
在 if 代码块作用域内可以访问 message。但是在作用域之外,该变量不可访问。以上是作用域的简短介绍。
好东西,都在文章底部,不妨拉倒底部看看惊喜
以下是 5 种有趣的情况,其中 JavaScript 作用域的行为与你预期的不同。你可能会研究这些案例以提高对作用域的了解,或者只是为面试做准备。
思考以下代码片段:
1constcolors=['red','blue','white'];
2
3for(leti=0,varl=colors.length;i<l;i++){
4console.log(colors[i]);//'red','blue','white'
5}
6console.log(l);//???
7console.log(i);//???
当你打印 l 和 i 变量时会发生什么?
console.log(l) 输出数字 3 ,而 console.log(i) 则抛出 ReferenceError。
l 变量是使用 var 语句声明的。你可能已经知道,var 变量仅受函数体作用域限制而并非代码块。
相反,变量 i 使用 let 语句声明。因为 let 变量是块作用域的,所以 i 仅在 for 循环作用域内才可访问。
把 l 声明从 var l = colors.length 改为 const l = colors.length。现在变量 l 被封装在 for 循环体内。
在以下代码段中:
1//ES2015env
2{
3functionhello(){
4return'Hello!';
5}
6}
7
8hello();//???
调用 hello() 会怎样?(代码段在 ES2015 环境中执行)
因为代码块为函数声明创建了作用域,所以在 ES2015 环境中调用 hello() 会引发 ReferenceError: hello is not defined。
有趣的是,在 ES2015 之前的环境中,在执行上述代码段时不会抛出错误。你知道为什么吗?请在下面的评论中写下你的答案!
你可以在代码块中导入模块吗?
1if(true){
2import{myFunc}from'myModule';//???
3myFunc();
4}
上面的脚本将触发错误:'import' and 'export' may only appear at the top-level。
你只能在模块文件的最顶级作用域(也称为模块作用域)中导入模块。
始终从模块作用域导入模块。另外一个好的做法是将 import 语句放在源文件的开头:
1import{myFunc}from'myModule';
2
3if(true){
4myFunc();
5}
ES2015 的模块系统是静态的。通过分析 JavaScript 源代码而不是执行代码来确定模块的依赖关系。所以在代码块或函数中不能包含 import 语句,因为它们是在运行时执行的。
思考以下函数:
1letp=1;
2
3functionmyFunc(p=p+1){
4returnp;
5}
6
7myFunc();//???
调用 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。
让我们选择重命名函数参数:
1letp=1;
2
3functionmyFunc(q=p+1){
4returnq;
5}
6
7myFunc();//=>2
函数参数从 p 重命名为 q。当调用 myFunc() 时,未指定参数,因此将参数 q 初始化为默认值 p + 1。为了评估 p +1,访问外部作用域的变量 p:p +1 = 1 + 1 = 2。
以下代码在代码块内定义了一个函数和一个类:
1if(true){
2functiongreet(){
3//functionbody
4}
5
6classGreeter{
7//classbody
8}
9}
10
greet();//???
newGreeter();//???是否可以在块作用域之外访问 greet 和 Greeter?(考虑 ES2015 环境)
function 和 class 声明都是块作用域的。所以在代码块作用域外调用函数 greet() 和构造函数 new Greeter() 就会抛出 ReferenceError。
必须注意 var 变量,因为它们是函数作用域的,即使是在代码块中定义的。
由于 ES2015 模块系统是静态的,因此你必须在模块作用域内使用 import 语法(以及export)。
函数参数具有其作用域。设置默认参数值时,请确保默认表达式内的变量已经用值初始化。
在 ES2015 运行时环境中,函数和类声明是块作用域的。但是在 ES2015 之前的环境中,函数声明仅在函数作用域内。
希望这些陷阱能够帮你巩固作用域知识!
《前端开发规范:命名规范、html规范、css规范、js规范》
《【规范篇】前端团队代码规范最佳实践》
《100个原生JavaScript代码片段知识点详细汇总【实践】》
《关于前端174道 JavaScript知识点汇总(一)》
《关于前端174道 JavaScript知识点汇总(二)》
《关于前端174道 JavaScript知识点汇总(三)》
《几个非常有意思的javascript知识点总结【实践】》
《都2020年了,你还不会JavaScript 装饰器?》
《JavaScript实现图片合成下载》
《70个JavaScript知识点详细总结(上)【实践】》
《70个JavaScript知识点详细总结(下)【实践】》
《开源了一个 JavaScript 版敏感词过滤库》
《送你 43 道 JavaScript 面试题》
《3个很棒的小众JavaScript库,你值得拥有》
《手把手教你深入巩固JavaScript知识体系【思维导图】》
《推荐7个很棒的JavaScript产品步骤引导库》
《Echa哥教你彻底弄懂 JavaScript 执行机制》
《一个合格的中级前端工程师需要掌握的 28 个 JavaScript 技巧》
《深入解析高频项目中运用到的知识点汇总【JS篇】》
《JavaScript 工具函数大全【新】》
《从JavaScript中看设计模式(总结)》
《身份证号码的正则表达式及验证详解(JavaScript,Regex)》
《浏览器中实现JavaScript计时器的4种创新方式》
《Three.js 动效方案》
《手把手教你常用的59个JS类方法》
《127个常用的JS代码片段,每段代码花30秒就能看懂-【上】》
《深入浅出讲解 js 深拷贝 vs 浅拷贝》
《手把手教你JS开发H5游戏【消灭星星】》
《深入浅出讲解JS中this/apply/call/bind巧妙用法【实践】》
《手把手教你全方位解读JS中this真正含义【实践】》
《书到用时方恨少,一大波JS开发工具函数来了》
《干货满满!如何优雅简洁地实现时钟翻牌器(支持JS/Vue/React)》
《手把手教你JS 异步编程六种方案【实践】》
《让你减少加班的15条高效JS技巧知识点汇总【实践】》
《手把手教你JS开发H5游戏【黄金矿工】》
《手把手教你JS实现监控浏览器上下左右滚动》
《JS 经典实例知识点整理汇总【实践】》
《2.6万字JS干货分享,带你领略前端魅力【基础篇】》
《2.6万字JS干货分享,带你领略前端魅力【实践篇】》
《简单几步让你的 JS 写得更漂亮》
《恭喜你获得治疗JS this的详细药方》
《谈谈前端关于文件上传下载那些事【实践】》
作者:lzg9527
作者:疯狂的技术宅
转发链接:https://mp.weixin.qq.com/s/XkEvgyhJ8S0xQS2kOY67Qw
js是单线程的,为什么可以执行异步操作呢?
这归结与浏览器(js的宿主环境)通过某种方式使得js具备了异步的属性。
区分进程和线程:
进程:正在运行中的应用程序。每个进程都自己独立的内存空间。例如:打开的浏览器就是一个进程。
线程:进程的子集,是独立的。线程在共享的内存空间中运行。
浏览器是多进程的。如下图:
console.log(\'a\');
}, 0);
console.log(\'b\');
以上就是浅谈javascript执行机制的详细内容,更多请关注网站的其它相关文章!
Demand feedback