作者丨Alexander Hafemann
译者 | 布加迪
用JavaScript编写第一段代码可能需要一天左右的时间,但深入了解其未知知识和背景知识可能让你在整个职业生涯受益无穷!
作用域(scope)
简而言之,作用域就是“你可以在代码中访问声明的地方”。
我们有两种作用域:全局作用域和局部作用域,区别在于你可以在代码的任何地方访问全局作用域,但局部作用域在块内声明,所以你只能在块内访问它们。
注意,var关键字在变量提升部分中的表现可能略有不同。
变量let和const的区别
现在我们知道了什么是作用域,所以可以猜测这里最大的区别之一就是这些关键字的作用域。
图1.图中所示的表比较了这些关键字
变量提升(hoisting)
你可能经常听到这个词!但这到底是什么呢?简而言之,变量提升是JavaScript中的一种机制,一些声明在执行之前执行该机制;比如冒泡,JS引擎会把它们提升到首位,并声明它们的位置在其他之前,比如用于变量声明的var关键字;用var引入的变量可以在赋值之前被调用,你会得到undefined的结果,或者用function关键字声明的函数可以在JavaScript中声明之前被调用。
IIFE
这个短语代表“立即调用的函数表达式”,这意味着声明一经定义就运行的函数,允许将变量和函数设为私有,并确保循环中的异步代码被正确执行。
柯里化(Curring)
这是一种处理JavaScript函数的高级技术,它实际上转换函数,让你可以在不同的步骤中向函数传递参数,并使其在不同的步骤中可以调用。
异步
在讨论事件循环和web worker方面的内容之前,我们应该弄清楚对JavaScript而言的异步是什么,以及当JavaScript是单线程语言时,它是如何处理的!
JavaScript是一种单线程同步编程语言,它本身不支持多线程或异步模式,但是借助浏览器(浏览器API)和JavaScript底层的某种机制,我们可以拥有异步JavaScript!
图2
上图确切地说明了JavaScript引擎和我们从浏览器获得的Web API所发生的事情,不妨解释一下。
JavaScript有一个名为“调用堆栈”(Call Stack)的简单列表,它逐一管理任务(堆栈算法),但是当异步任务被传递时,JavaScript会把它弹出到web API,浏览器就会处理它;比如setTimeout API,当异步对象的结果准备好时,浏览器会通过底层的某种机制把它调回到堆栈中。
事件循环
还记得上面我告诉过你,异步对象在后台完成后会返回到调用堆栈中吗?处理这一机制的部分被称为“事件循环”。
事件循环会不断检查调用堆栈,如果里面没有任务而且是空闲的,它会按优先级把对象推送到调用堆栈中。
图3
回调和微任务队列
想象一下,有两个异步任务在同一秒内完成,它们都刚刚从web API返回,那么哪一个会先被推送到回调?
JavaScript对此有一个机制,它将回调请求分为两个部分:微任务和宏任务。
图4
宏任务队列在计时器到期后从setTimeout() API获得普通的回调函数。
宏任务的优先级低于用于将回调函数获取到事件循环的微任务队列。
微任务队列通过承诺(Promises)和变异观察者(Mutation Observer)获取回调函数。
原文链接:
https://javascript.plainenglish.io/javascript-deep-concepts-you-should-know-dde14aafd8d2
https://javascript.plainenglish.io/javascript-deep-concepts-you-should-know-8965d4e409d3