你所知道的JS变量作用域

变量的作用域,指的是变量在脚本代码中的可读、可写的有效范围,也就是脚本代码中可以使用这个变量的区域。在ES6之前,变量的作用域主要分为全局作用域、局部作用域(也称函数作用域)两种;在ES6及其之后,变量的作用域主要分为全局作用域、局部作用域、块级作用域这3种。相应作用域变量分别称为全局变量、局部变量、块级变量。全局变量声明在所有函数之外;局部变量是在函数体内声明的变量或者是函数的命名参数;块级变量是在块中声明的变量,只在块中有效。

变量的作用域跟声明方式有密切的关系。使用var声明的变量的作用域有全局作用域和局部作用域,没有块级作用域;使用let和const声明的变量有全局作用域、局部作用域和块级作用域。

注:严格意义的全局变量都属于Window对象的属性,但let和const声明的变量并不属于Windows对象,所以它们并不是严格意义上的全局变量,在此仅仅从它们的作用域这个角度来说它们是全局变量的。

由于var支持变量提升,所以var变量的全局作用域是对整个页面的脚本代码有效;而let和const不支持变量提升,所以let和const变量的全局作用域指的是从声明语句开始到整个页面的脚本代码结束之间的整个区域,而声明语句之前的区域是没有效的。同样,因为var支持变量提升,而let和const不支持变量提升,所以使用var声明的局部变量是在整个函数有效,而使用let和const声明的局部变量从声明语句开始到函数结束之间的区域有效。需要注意的是,如果局部变量和全局变量同名,则在函数作用域中,局部变量会覆盖全局变量,即在函数体中起作用的是局部变量;在函数体外,全局变量起作用,局部变量无效,此时引用局部变量将出现语法错误。在块开始到块级变量声明语句之间区域为暂时性死区,在这个区域,块级变量没有效。

另外,在非严格运行模式中,变量可以不需要声明,这些没有声明的变量,不管在哪里使用都属于全局变量。通常不建议变量不声明而直接使用,因为这样有可能会产生一些不易发现的错误。

1<!DOCTYPE html> 2<html> 3<head> 4 <title></title> 5</head> 6<body> 7<script> var v1 = "JavaScript"; // 全局变量 8   let v2 = "JScript"; // 全局变量 9   let v3 = "Script"; // 全局变量 10    11   scopeTest(); // 调用函数 12   function scopeTest(){ 13    var lv = "aaa";//局部变量 14        var v1 = "bbb";//局部变量 15        let v2 = "ccc";//局部变量 16        if(true){ 17            let lv = "123"; 18            console.log("块级输出的lv= " + lv); // 123 19        } 20         21        console.log("函数体内输出的lv = " +lv); //aaa 22        console.log("函数体内输出的v1 = " +v1); //bbb 23        console.log("函数体内输出的v2 = " +v2); //ccc 24        console.log("函数体内输出的v3 = " +v3); //Script 25        console.log("函数体内输出的v4 = " +v4); // undefined, v4为全局变量,赋值在后面,var存在变量提升,因而值为undefined 26   } 27   var v4 = "VB"; //全局变量 28   console.log("函数体外输出的lv = " +lv); // 报ReferenceError错误 29   console.log("函数体内输出的v1 = " +v1); //JavaScript 30   console.log("函数体内输出的v2 = " +v2); //JScript 31   console.log("函数体内输出的v3 = " +v3); //Script 32   console.log("函数体内输出的v4 = " +v4); // VB</script> 33</body> 34</html> 35

上述脚本代码分别声明了4个全局变量、3个局部变量和1个块级变量。在scopeTest函数体外,变量v1、v2、v3和v4为全局变量;在scopeTest函数体内,lv、v2是全局变量;在if判断块中,lv是块级变量。我们看到,局部变量v1和v2与全局变量v1和v2同名,在scopeTest函数体内,局部变量v1和v2有效,因而在函数体这2个变量的输出结果分别为bbbccc;在函数体外全局变量v1和v2有效,因而在函数体外,这2个变量的输出结果分别为JavaScriptJScript。另外,块级变量lv和局部变量lv同名,在if判断块中,块级变量lv有效,因而在块中输出的结果为123,而在块外,局部变量lv有效,lv变量的输出结果为aaa。另外,全局变量v3和v4在函数体中没有被覆盖,因而输出的是全局变量的值,所以v3在函数体外和体内输出结果都是Script,而v4变量的赋值在函数调用的后面,因而在函数体中的v4输出结果为undefined,而在函数体外的输出是在声明之后,所以结果为VB。lv是局部变量,因而在函数体外访问会报ReferenceError错误。

总结:块级变量在块内覆盖局部变量,局部变量在函数体内覆盖全局变量,没有被覆盖的全局变量在函数体内、外都有效。


欢迎关注我的公众号前端历劫之路

回复关键词电子书,即可获取12本前端热门电子书。

回复关键词红宝书第4版,即可获取最新《JavaScript高级程序设计》(第四版)电子书。

关注公众号后,点击下方菜单即可加我微信,我拉拢了很多IT大佬,创建了一个技术交流、文章分享群,期待你的加入。

本文转转自微信公众号前端历劫之路原创https://mp.weixin.qq.com/s/ypfKD0mfaaHWNnS54Z67DA,如有侵权,请联系删除。

点赞
收藏

评论区

加载中...

相关推荐

手写Java HashMap源码

HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22

JS核心原理理解闭包

前置概念在正式看闭包之前,我们先来学习一下前置知识,那就是JS中的作用域,我们知道,在ES5之中,作用域分为两种:全局作用域和函数作用域,随着ES6的到来,新增了块级作用域,想更好的理解闭包,那么搞清楚作用域是首要条件全局作用域我们知道,对于变量而言,我们一般会分成两类:全局变量和局部变量,一般定义在最外围环境的为全局变量,定义在函数当中的为局部变量,在we

JS - 作用域

一、作用域作用域,即变量(变量作用域又称上下文)和函数生效(能被访问)的区域或集合换句话说,作用域决定了代码区块中变量和其他资源的可见性举个例子function myFunction(){    let inVariable  "函数内部变量";}myFunction();//要先执行这个函数,否则根本不知

一篇文章带你了解JavaScript作用域

在JavaScript中,对象和函数也是变量。在JavaScript中,作用域是你可以访问的变量、对象和函数的集合。JavaScript有函数作用域:这个作用域在函数内变化。一、本地JavaScript变量一个变量声明在JavaScript函数内部,成为函数的局部变量。局部变量有局部作用域:它们只能在函数中访问。JS://codeherecann

为你解惑JS作用域和作用域链知识

原文链接:变量作用域一个变量的作用域(scope)是程序源代码中定义这个变量的区域。全局变量拥有全局作用域,在JavaScript代码中的任何地方都是可以访问的。然而在函数内声明的变量只能在函数体内访问,它们是局部变量,作用域是局部性的。函数参数也是局部变

Javascript 变量 var与不var的区别

1.在函数作用域内加var定义的变量是局部变量,不加var定义的就成了全局变量。使用var定义var a  'hello World';function bb(){    var a  'hello Bill';    console.log(a);   }bb()   // 'hello Bill'conso