预编译 与 闭包

 let 存在 暂时性死区

在块级作用域内,若存在用let命令声明的变量,则所在区块对该变量形成封闭作用域,也就是该变量无视外部的同名变量。而又因为不存在变量提升,所以在该区块中,不能在声明前使用该变量。

 

语法 

  1. JavaScript 脚本的运行由两个阶段组成:预编译阶段执行阶段,先进行预编译,再执行语句;                       
  2. 2. 预编译,简单理解,就是在内存中开辟一块空间,用来存放变量和函数。在 JavaScript 中,JavaScript 会在内存中为使用 <code>var</code> 关键字声明的变量和使用 <code>function</code> 关键字声明的函数开辟一块空间,用来存放使用这两者声明的变量和函数;
  3. 在预编译时,<code>function</code> 的优先级比 <code>var</code> 高,
  4. 注意:预编译时并不会对变量进行赋值(即不会进行初始化),变量赋值是在 JavaScript 脚本执行阶段进行的。
  5. 变量声明 提升(*注意是变量声明
    1. 重复声明时:首先,编译器对代码进行分析拆解,当遇见var a,则询问作用域是否已存在叫a的变量,若不存在,则要求作用域声明一个新的变量a,若已存在,则忽略var继续向下编译。
  6. 函数声明 整体提升

tip:JS函数的调用永远都是在函数声明下面调用,即使你的调用是写在函数声明之前的,它隐式也是在函数声明下调用的,细节看下面预编译时 函数声明整体提升。

预编译分为全局预编译和局部预编译,全局预编译发生在页面加载完成时执行,而局部预编译发生在函数执行的前一刻。

全局预编译的步骤

  1. 创建GO(Global Object,全局执行期上下文,在浏览器中为window)对象;
  2. 寻找var变量声明,并赋值为undefined;
  3. 寻找function函数声明,并赋值为函数体;
  4. 执行代码。

函数预编译的步骤

  1. 创建AO对象,执行期上下文(后面更新关于执行期上下文详解)。
  2. 寻找函数的形参和变量声明,将变量和形参名作为AO对象的属性名,值设定为undefined.
  3. 将形参和实参相统一,即更改形参后的undefined为具体的形参值。
  4. 寻找函数中的函数声明,将函数名作为AO属性名,值为函数体。

Tips:1. 函数表达式不是函数声明,故不可以变量提升。

2. if语句,在预编译阶段先无视他就可。

3. 函数声明在与编译阶段已经整体提升,所以在代码执行阶段可以直接跳过。

tip:预编译阶段发生变量声明和函数声明,没有初始化行为(赋值),匿名函数不参与预编译 。只有在解释执行阶段才会进行变量初始化 。

预编译中

  1. 一切声明的全局变量和未经声明的变量,全归window所有。

预编译末 执行前

  1. 首先JavaScript的执行过程会先扫描一下整体语法语句,如果存在逻辑错误或者语法错误,那么直接报错,程序停止执行,没有错误的话,开始从上到下解释一行执行一行。

待续:这节可以和函数被调用时都会发生什么联系起来。

猜你喜欢

转载自blog.csdn.net/qq_52317104/article/details/120722241
今日推荐