当前位置:网站首页>预解析与作用域

预解析与作用域

2022-06-11 23:44:00 InfoQ

预解析

        不是告诉你怎么写代码
        遵循代码的执行机制, 怎么才能写出来规范的代码
      预: 在所有代码执行之前
        解析: 解释, 对代码进行通读并解释

  解释的使用方法

        1. var 关键字
        在代码执行之前会把 var 关键字定义的变量提前声明
        2. 声明式函数
          会把这个函数名在所有代码执行之前声明, 并且赋值为一个函数
       
 注意: 赋值式函数
          var fn = function () {}
          按照 var 的规则进行解析

 预解析案例

        有 变量 的解析
        有 声明式函数 的解析
        问题: 变量名 和 函数名 重名了该如何去解决
        当 函数 和 变量 重名的时候, 以预解析阶段的函数为准

 作用域

 作用域分为两种,一种是全局作用域,另一种是私有作用域
        1. 全局作用域
          打开一个页面就是一个全局作用域
          全局作用域, 通常值 window系统
        2. 私有作用域(局部作用域)
          **只有函数生成私有作用域**
      3.作用域的上下级关系
      你的函数写在哪个作用域下
      你就是谁的子级作用域
      作用域的上下级关系干什么用
        为了确定变量的使用范围

       

 三个机制

          
1. 变量定义机制
          有 var 关键字
            声明式函数
            var num
            function fn() {}
          2. 变量使用机制
            你需要拿到某一个变量的值来使用
            n++
            console.log(abc)
          3. 变量赋值机制
            一定要有赋值符号
          num = 100
            num += 100
var color = "blue"; 
function changeColor() { 
 let anotherColor = "red"; 
 function swapColors() { 
 let tempColor = anotherColor; 
 anotherColor = color; 
 color = tempColor; 
 // 这里可以访问 color、anotherColor 和 tempColor 
 } 
 // 这里可以访问 color 和 anotherColor,但访问不到 tempColor 
 swapColors(); 

// 这里只能访问 color 
changeColor(); 

null
上图 展示了前面这段代码的作用域链。分级展示不能更好的帮助大家理解作用域的层级。

变量的三个机制


变量的定义机制

        一个变量(函数)
        在哪一块作用域里面定义
        就只能在当前作用域,和下级作用域里面使用
        无法在上一级作用域使用

      变量使用机制

        当你需要使用一个变量(函数)
        首先要在自己的作用域内查找, 如果有, 直接使用
        如果没有, 取上一级作用域查找, 如果有, 直接使用
        如果还没有, 再去上一级查找
        直到 window 都没有, 那么就 **报错**

      

变量赋值机制

        当你需要给一个变量(函数名)赋值的时候
        会首先在自己作用域内查找, 如果有, 直接赋值
        如果没有, 取上一级作用域查找, 有就赋值
        还没有, 再去上一级作用域查找, 有就赋值
        直到 window 都没有, **把这个变量定义为全局变量, 在进行赋值**

 1. 使用 var 的函数作用域声明 在使用 var 声明变量时,变量会被自动添加到最接近的上下文。在函数中,最接近的上下文就是函 数的局部上下文。

function add(num1, num2) { 
 var sum = num1 + num2; 
 return sum; 

let result = add(10, 20); // 30 
console.log(sum); //这个会报错

null
 注意 
未经声明而初始化变量是 JavaScript 编程中一个非常常见的错误,会导致很多问题。 在初始化变量之前一定要先声明变量。

 2. 使用 let 的块级作用域声明 ES6 新增的 let 关键字跟 var 很相似,但它的作用域是块级的,这也是 JavaScript 中的新概念。块 级作用域由最近的一对包含花括号{}界定。

 let 与 var 的另一个不同之处是在同一作用域内不能声明两次。重复的 var 声明会被忽略,而重 复的 let 声明会抛出 SyntaxError。
var a;
 var a;// 不会报错
{
 let b;
 let b;
 }


null
 let 的行为非常适合在循环中声明迭代变量。使用 var 声明的迭代变量会泄漏到循环外部,这种情 况应该避免。

 3. 使用 const 的常量声明 除了 let,ES6 同时还增加了 const 关键字。使用 const 声明的变量必须同时初始化为某个值。 一经声明,在其生命周期的任何时候都不能再重新赋予新值。

const a; // SyntaxError: 常量声明时没有初始化
const b = 3; 
console.log(b); // 3 
b = 4; // TypeError: 给常量赋值
const 除了要遵循以上规则,其他方面与 let 声明是一样的。
 
注意
 开发实践表明,如果开发流程并不会因此而受很大影响,就应该尽可能地多使用 const 声明,除非确实需要一个将来会重新赋值的变量。这样可以从根本上保证提前发现 重新赋值导致的 bug。
 总结:
 JavaScript解释阶段便会确定作用域规则,因此作用域在函数定义时就已经确定了,而不是在函数调用时确定,但是执行上下文是函数执行之前创建的。执行上下文最明显的就是this的指向是执行时确定的。而作用域访问的变量是编写代码的结构确定的。
 作用域和执行上下文之间最大的区别是:
执行上下文在运行时确定,随时可能改变;作用域在定义时就确定,并且不会改变

原网站

版权声明
本文为[InfoQ]所创,转载请带上原文链接,感谢
https://xie.infoq.cn/article/57e99017a249c406eb4f41401