当前位置: 首页 > Web前端 > JavaScript

JS中的块作用域和阴影效果

时间:2023-03-27 01:45:56 JavaScript

JS中的代码块是什么?我们的程序是由语句组成的,语句是按照自上而下的顺序一条一条执行的。代码块(block)也称为复合语句(coumpoundstatement),其作用是通过“{}”将多个语句组合在一起。{//复合语句vara=10;console.log(a);}那么为什么要将多个语句组合在一起呢?因为我们可以把多条语句“打包”在一起,放在一个JS只期望一条语句的地方。这句话看起来有点晦涩,但是结合代码就很容易理解了:下面的代码中,在条件判断语句if(true)之后,只写一条语句,不用写{}也能正常运行。如果(真)console.log('你好');//只写一行语句,程序也能正常运行//输出hello但是如果我们想在条件判断之后做更多的事情,就需要使用{},在这个JS中只希望有更多的语句,其中一条放置语句:if(true){console.log('hello');console.log('世界');console.log('再见');}块级效果什么是域?块作用域(blockscope)是指所有在花括号内的变量和函数只能在花括号围起来的区域内访问,不能在花括号外访问。上面的代码:{vara=10;//var在全局范围内letb=20;常量c=30;//let和const都在代码块范围内console.log(a);控制台日志(b);控制台日志(c);}console.log(a);控制台日志(b);控制台日志(c);将上面的代码放到调试工具中,可以看到var、let和const的声明属于不同的作用域。当代码在花括号内执行时,程序可以访问两个作用域(代码块和全局)的变量,如下图:但是当代码在花括号外执行时,会报错,因为当在代码块中语句执行后,代码块作用域消失(从栈中弹出),从而只剩下一个全局作用域,其中只绑定了一个变量a,变量b和c无法访问:因此,程序结束控制台的输出是:由于在块级作用域外打印b时出错,程序会在这里停止运行,但可以想象在打印c时也会出现同样的错误。什么是阴影效应?在不同范围内具有相同名称的变量会触发阴影。看var的阴影效果代码,猜猜结果:vara=100;{变量a=10;让b=20;常量c=30;控制台日志(一);控制台日志(b);console.log(c);}控制台打印如下:花括号中的变量a会使第1行声明的变量a失效,称为阴影效应。因为这两个在全局范围内把a指向a。那么,如果在括号外再次打印a怎么办?变量a=100;{变量a=10;让b=20;常量c=30;控制台日志(一);控制台日志(b);console.log(c);}console.log(a);//猜猜结果我们来调试工具,加个断点:当程序执行完第一行,全局变量a的值为100;当程序执行完第三行,全局变量a的值翻倍第二次声明中的vara=10被重新赋值为10,这两条语句中的vara都指向同一个全局变量a:因此,控制台打印如下:let的阴影效果看代码猜猜结果:letb=100;{vara=10;让b=20;常量c=30;控制台日志(一);控制台日志(b);console.log(c);}console.log(b);consoleprint如下:花括号中的变量b也会使第1行声明的变量b失效,形成变量阴影。但与var不同的是,let具有块级作用域,因此最后一行的b仍然打印在第1行声明的b上。我们再次进入调试工具,加个断点:可以清楚的看到程序中有3个作用域,1个是全局作用域,剩下的2个是块级作用域(代码块和脚本)。虽然第1行的let声明是全局的,但是let关键字会自己创建一个块级作用域(图中的脚本),它在内存中的一个单独空间中,存储值为100的变量b。花括号中的变量b在内存中的另一个独立空间中,存储了另一个值为20的变量b。因此,程序第7行的b访问了代码块中的变量b,第10行访问了脚本中的变量b(也可以理解为另一个代码块)。const的着色效果const的着色效果和let一样。之前的代码稍作修改:constc=100;{变量a=10;让b=20;常量c=30;控制台日志(一);安慰。日志(b);console.log(c);}console.log(c);控制台打印如下:函数中的阴影效果阴影效果不仅发生在块级作用域中,也发生在函数中。看代码:constc=100;functionx(){constc=30;console.log(c);}x();console.log(c);控制台打印如下:Whatisillegalshadowing?如果使用var关键字来触发阴影效果,是完全可行的,如下:vara=100;{vara=20;控制台日志(一);//20}同理,使用let关键字触发阴影效果也有效For:leta=100;{让a=20;控制台日志(一);//20}但是如果用var覆盖let,程序运行前会报错:leta=100;{变量a=20;控制台日志(一);//语法错误}那么,如果用let来覆盖var,是不是也会报错呢?看代码:vara=100;{让a=20;控制台日志(一);}控制台打印结果如下:程序没有报错。那么为什么用var覆盖let会报错呢?因为阴影效应的原则是:重复声明的语句不能超出自己的范围。即当我们在块级作用域中使用var重新声明变量a时,由于var只有全局作用域或函数作用域,块级作用域无法限制var的声明,此时vara会超出其自身的位置作用域,而let关键字不允许在同一个作用域内重复声明,所以程序报错。因此,只需要把上面代码中的块级作用域改成函数作用域,程序就不会报错了:vara=100;functionx(){vara=20;控制台日志(一);}X();//20console.log(a);//100使用const触发阴影效果和let是一样的,不再赘述。常量b=100;{常量b=20;控制台日志(b);//20}块级作用域和词法作用域词法作用域是在词法阶段定义的作用域。换句话说,词法作用域由编写代码时编写变量和块作用域的位置决定。词法作用域的变量查找规则是:如果在当前作用域中找不到该变量,则在上层作用域中查找,以此类推。块级范围也享有相同的查找规则:consta=20;{consta=100;{常量=200;控制台日志(一);//200}}consta=20;{consta=100;{常量=200;}}console.log(a);//20consta=20;{consta=100;{console.log(a);//100Lookuptheupperscope}}以上就是JavaScript中块级作用域和阴影效果的知识。