Javascript 执行机制

面试
Javascript 执行机制

变量提升

把【变量声明部分】和【函数声明部分】提升到代码开头的机制;

在编译阶段,Javascript 解释器会扫描代码,并找到所有的变量声明,无论变量声明在代码的哪个位置,都会在代码执行阶段之前被提升到作用域的顶部;

作用域

作用域决定了代码块中的变量可以在哪里被访问。

全局作用域:在任何地方被访问,在浏览器中,全局作用域是 window 对象。

函数作用域:在函数内部被访问。

块级作用域letconst 关键词用于声明在特定代码块(通常由一个花括号包围的区域),允许变量在如 if 语句或 for 循环中被局部化。

模块作用域:每个模块文件都有自己的作用域,变量或函数在模块内部声明,不会污染全局作用域,要在其他模块中使用这些变量或函数,必须显式导出并在另一个模块中导入它们。

作用域链:

在一个嵌套的作用域中,如果内部作用域没有声明某个变量,解释器会一直向上级作用域查找,直到找到该变量或者达到全局作用域。

this

执行上下文;

全局执行上下文中的 this:指向 window 对象;

函数执行上下文中的 this:默认情况下调用一个函数,其上下文中的 this 也指向 window 对象;

设置函数执行上下文的 this 指向

通过 call 方法设置:foo.call(bar)

通过对象调用方法设置:myObj.showThis()

通过构造函数设置:new CreateObj()

箭头函数

嵌套函数里的 this 不会从外层函数继承,箭头函数可以解决这个问题,它不会创建自身的执行上下文,它的 this 取决于外部函数。

闭包

闭包的形成需要满足三个条件:

首先,有一个【内层函数】;

其次,内层函数【引用】了【外层函数的变量】;

最后,外层函数【执行完毕】后,内层函数在【其他地方被引用】;

这时,内层函数依然可以使用外层函数里的变量,这就是闭包;

原型链

作用:通过对象之间的原型关系,实现属性和方法的继承;

原型链:每个对象都有一个原型(prototype),它是一个对象或 null,访问一个对象的属性或方法时,如果该对象本身没有定义该属性或方法,JavaScript 引擎会自动沿着原型链向上查找,直到找到对应的属性或方法或者达到原型链的顶端;

函数的原型

函数对象特有的属性,由函数对象的 prototype 属性表示,包含可被继承的属性和方法,用于实现基于原型的继承;

对象的原型

__proto__ 表示,指向对象的原型对象,每个普通对象都具有的属性,用于实现属性和方法的继承;

关系

函数的原型对象也是一个普通对象,继承自 Object;

事件循环

所有同步任务在主线程上执行,形成了一个【执行栈】;

主线程之外还有一个【任务队列】,只要异步任务有了执行结果,就在任务队列当中放置一个事件;

主线程的同步任务执行完毕,就会读取任务队列,对应的异步任务会结束等待状态进入执行栈,开始执行;

宏任务和微任务

主线程里的宏任务执行结束,进入消息队列,执行消息队列里的微任务,结束之后,再执行消息队列里的内层宏任务;

微任务

process.nextTick

Promise.then/catch/finally

await

宏任务

setTimeout