写点什么

预解析与作用域

作者:Jason199
  • 2022 年 6 月 11 日
  • 本文字数:2206 字

    阅读完需:约 7 分钟

预解析与作用域

预解析

        不是告诉你怎么写代码

        遵循代码的执行机制, 怎么才能写出来规范的代码

      预: 在所有代码执行之前

        解析: 解释, 对代码进行通读并解释


 解释的使用方法

        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(); 
复制代码


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

变量的三个机制


变量的定义机制

        一个变量(函数)

        在哪一块作用域里面定义

        就只能在当前作用域,和下级作用域里面使用

        无法在上一级作用域使用

      变量使用机制

        当你需要使用一个变量(函数)

        首先要在自己的作用域内查找, 如果有, 直接使用

        如果没有, 取上一级作用域查找, 如果有, 直接使用

        如果还没有, 再去上一级查找

        直到 window 都没有, 那么就 **报错**

      变量赋值机制

        当你需要给一个变量(函数名)赋值的时候

        会首先在自己作用域内查找, 如果有, 直接赋值

        如果没有, 取上一级作用域查找, 有就赋值

        还没有, 再去上一级作用域查找, 有就赋值

        直到 window 都没有, **把这个变量定义为全局变量, 在进行赋值**


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


function add(num1, num2) {  var sum = num1 + num2;  return sum; } let result = add(10, 20); // 30 console.log(sum); //这个会报错
复制代码


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


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


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

var a; var a;// 不会报错{ let b; let b; }
复制代码


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 的指向是执行时确定的。而作用域访问的变量是编写代码的结构确定的。

作用域和执行上下文之间最大的区别是:执行上下文在运行时确定,随时可能改变;作用域在定义时就确定,并且不会改变


发布于: 刚刚阅读数: 4
用户头像

Jason199

关注

还未添加个人签名 2022.04.29 加入

一条努力上岸的咸鱼

评论

发布
暂无评论
预解析与作用域_js_Jason199_InfoQ写作社区