JS的作用域和预解析
2021-04-25 12:28
标签:为什么 xxx 编写 语句 全局变量 理解 赋值语句 答案 输出 当我们使用Js 来编写一个函数的时候,总是会分不清,自己所声明的变量到底是全局变量,还是局部变量,这就牵扯到了作用域的问题。以及在函数执行的时候,函数内部的变量与全局变量及输出结果,在不同状况下的关系问题。下面就让我来举例说明一下。 作用域: 指的是代码对不同的“范围”的划分。 划分规则: 1 全局是一个作用域 这个作用域叫做全局作用域 2 只有函数,可以划分这么一个“范围”(作用域) 这样划分出来的作用域叫做私有作用域。 划分规则的应用对象: 变量 所以我们可以理解为: 作用域 划分了一个所有变量各自起作用的区域。 作用域的查找机制: 一个代码中使用到了某一个变量 首先,在这条代码当前所在的作用域中查找,如果找到了就使用 如果没有找到 向上级作用域查找,如果找到了就使用 如果没有找到 向上级作用域查找,如果找到了就使用 如果没有找到 …… 重复这个过程,直到找到了,或者到了全局作用域还没有找到。此时会报一个错误 xxx is not defined 预解析: 指的是浏览器JS引擎在执行代码的过程之前,会先进行“通读”代码,在这个过程中,会将所有遇见的var定义的变量和函数声明的函数提升。 提升的位置: 如果是script标签,提升到当前script标签的最开头 如果是函数,提升到函数的函数体的最开头 作用域的特点 作用域的机制 作用域是针对变量的起作用的范围。 而变量又分为“使用变量”和“赋值变量” 使用变量 又叫做访问变量 出现在表达式中,赋值语句右侧。 访问变量规则: 当访问变量的时候,会先查看当前作用域中是否存在该变量,如果有,就使用。如果没有,就将会向上一层级作用域中寻找。依次向上,直到找到,或者到了全局作用域中还没有找到,就会报错。 赋值变量 也叫做修改变量 只出现在赋值语句左侧 赋值变量规则: 当对一个变量进行赋值的时候,会先查看当前作用域中是否存在该变量,如果有,就赋值。如果没有,就向上一层级查找。依次向上,直到找到,或者到了全局作用域中还没有找到,就会在全局作用域中悄悄的声明这个变量并赋值。 千万不要使用这个特点 切记,切忌。 // 当前是全局作用域 var num = 100; // 在全局作用域中定义的变量 // 定义一个函数 function demo() { var num = 101; // 这是在函数作用域中定义的变量 console.log(num); } // 执行函数 demo(); // 101 解释: 当在函数内部访问变量num的时候,先看当前作用域中是否有num 找到了! 于是就用101 输出101 var num = 100; // 在全局作用域中定义的变量 // 定义一个函数 function demo() { // var num; // 因为声明提升的原因 代码其实是这样子的 console.log(num); var num = 101; // 这是在函数作用域中定义的变量 虽然定义是在这里 但是提升了 } // 执行函数 demo(); // undefined 解释:依旧是作用域的问题,但是因为输出代码在前面,所以有些同学可能会误以为会输出100 但是不要忘记 预解析!!! var num = 100; // 在全局作用域中定义的变量 // 定义一个函数 function demo() { var num = 101; } // 执行函数 demo(); // num是多少 console.log(num); // 100 解释:作用域的问题,因为输出的代码是在全局作用域中的,所以会直接访问全局中的变量 而与函数内部的变量无关 var num = 100; // 在全局作用域中定义的变量 // 定义一个函数 function demo() { num = 101; } console.log(num); // 100 // 执行函数 demo(); // num是多少 console.log(num); // 101 读代码: 1 提升 2 给全局中的num赋值为100 3 执行函数 将num赋值为101 问题的关键在于:修改的这个num到底是不是全局中的? 答案就是: 依旧是就近原则, 如果当前作用域中有声明的num变量 就修改它 如果没有向上寻找 如果找到了就修改它 如果没有找到再向上寻找 重复这个过程 直到找到或者到了全局作用域中还没有找到,就会在全局中声明这个变量并赋值 // 如果一个变量没有通过var声明 就直接赋值 num = 101; // 这种不经过声明就直接赋值而且还不会报错的特点属于JS的糟粕之一。一定不要使用。 console.log(num); // 101 console.log(num); num = 101; 这种情况下会报错 因为num没有经过定义就被使用 疑问: console.log(num)在使用num 难道 num = 101 不是在使用num吗? 为什么第一条console代码就会报错 而num = 101就不会报错? 因为第一个是在“访问”变量 而第二个是在“赋值” function demo() { num = 11; } demo(); console.log(num); 解读: 当demo执行的时候, num = 11 被执行 先查找num是否在当前作用域中存在,结果发现没有 没有就向上寻找,到达了全局作用域,也没有,于是就在全局作用域中,声明了该变量 所以当输出num时候,已经声明并赋值完毕 所以可以输出 当demo不执行的时候,就不会执行到这条代码 于是整个过程不会发生, num就没有被声明在全局 此时输出num时,是在访问num变量 会报错 JS的作用域和预解析 标签:为什么 xxx 编写 语句 全局变量 理解 赋值语句 答案 输出 原文地址:https://www.cnblogs.com/tongguilin/p/12229520.html