块级作用域与嵌套、let、暂时性死区

函数的作用域、全局作用域
kiss原则 keep it simple stupid

let 块级作用域

一、什么叫块?
一个{}就是一个块,比如

if{}
function(){}
for(var i = 0; i < 10; i++){}

二、let的特征
1 、 l e t 在同一作用域下不可重复声明 \color{#008B8B}1、let在同一作用域下不可重复声明 1let在同一作用域下不可重复声明
var可以重复声明,后面的会覆盖前面的

var a = 1;
var a = 2;

let重复声明会报错,在全局作用域,函数作用域都是

let a = 1;
let a = 2;

在这里插入图片描述
这种写法会和上面报一样的错误,

function test(){
   let a = 1;
   var a = 2;
 }

这样写也会报错,因为形参在函数作用域中相当于一个临时变量,在函数预编译的时候已经被定义了

function test(a){
let a = 10;
}
test(12);

也就说明了在同一作用域下,只要是用声明过的变量,就不能在用let重新声明,如果在不同的作用一下,就不会出现问题

function test(a){
   {
//有一个单独的作用域
     let a = 1;
   }
   console.log(a)//10
 }
 test(10)

2 、 l e t 不会提升,因此会产生一个暂时性死区(提升范围之前就叫暂时性死区( t e m p o r a l d e a d z o n e )) \color{#2E8B57}2、let 不会提升,因此会产生一个暂时性死区(提升范围之前就叫暂时性死区(temporal dead zone)) 2let不会提升,因此会产生一个暂时性死区(提升范围之前就叫暂时性死区(temporaldeadzone))
let声明的变量没有提升也就是说let声明的变量,在声明之前使用它是不允许的,只能在代码执行到变量声明之后执行

     function test(){
       console.log(a);
       let a = 1;
     }
     test();

在这里插入图片描述
打印undefined

var a = a;
console.log(a);//undefined

在这里插入图片描述

报引用错误

let b = b;
console.log(b);//报错

在这里插入图片描述
当y被赋值给x的时候y还没有被定义,也是暂时性死区造成的问题,因为函数参数默认赋值的时候,形式参数不存在变量提升问题,就相当于形式参数是let声明的

   function test(x=y, y=2){
       console.log(x, y);
     }
    test();

let 不会提升就会有一个问题 typeof的问题,typeof 不安全,如果使用 typeof 检测在暂时性死区中的变量
在使用var的时候typeof一个为声明的变量a,会打印undefined

typeof a

如果这样写

console.log(typeof a);//报错
let a;

会报错
在这里插入图片描述
3 、只能在当前的块级作用域下生效 \color{#808000}3、只能在当前的块级作用域下生效 3、只能在当前的块级作用域下生效
因为不在同一作用域下,就会报错

  {
      let a = 1;
    }
    console.log(a);
if(1){
      let a = 1;
    }
    console.log(a);

在这里插入图片描述
for循环的块级作用域下的问题

	//这样不会报错,因为一直在循环,不会走到打印a的代码
    for(;1;){
    let a = 3;
    }
    console.log(a);

报错,在全局作用域下访问不到i

 for(let i = 0; i < 5; i++){
  
  }
  console.log(i);

第二种写法,因为第一次for循环,全局定义了i=0;循环完以后i变成10,在第二个循环中执行arr中的函数又重新定义了i=0,前面的值就被覆盖了,当arri执行的时候,每一次循环i的值变一次,所以打印出了0-5

 var arr = [];
  for(var  i = 0; i < 5; i++){
  arr[i] = function(){
    console.log(i);
  }
  }
  //这样写打印五个5
  for(var j = 0; j < 5; j++){
    arr[j]();//打印五个5
  }
 // 这样写,打印0-5
   for(var i = 0; i < 5; i++){
    arr[i]();
  }

在for循环中(){}是否是同一作用域?
let会产生块级作用域,因此for循环中的()和{}不是同一作用域

  for(var  i = 0; i < 5; i++){
      i = 'a'
    console.log(i);//只打印一次a
  }
    for(let  i = 0; i < 5; i++){
      var i = 'a'
    console.log(i);//还是只打印一次a
  }
  for(let i = 0; i < 5; i++) {
	var i = 'a';
	console.log(i); // SyntaxError: Identifier 'i' has already been declared
}
  for(let  i = 0; i < 5; i++){
      let i = 'a'
    console.log(i);//打印5个i
  }

for循环中使用let

不是let创建了块级作用域,而是由于for的initialization block中用了let,触发了一种作用域创建机制
特殊机制
初始化照样做,
而每一次迭代的时候会发生以下事情:
1、系统会为for loop body创建新的词法作用域

{
  arr[i] = function(){
 	 console.log(i);
  }
  }

2、在词法作用域中新声明一个i(let i)
3、将上一次迭代或者初始化的值赋给这个新的i变量
4、对新的词法作用域内进行i操作 i++
所以我们可以将for中使用let声明变量执行循环的过程写成以下形式

  var arr = [];
  var memo;
  {
    let i = 0;
    arr[i] = function(){
      console.log(i);
    }
    memo = i + 1;
  }
  {
    let i = memo;
    arr[i] = function(){
      console.log(i);
    }
    memo = i + 1;
  }
  {
    let i = memo;
    arr[i] = function(){
      console.log(i);
    }
    memo = i + 1;
  }
  {
    let i = memo;
    arr[i] = function(){
      console.log(i);
    }
    memo = i + 1;
  }
  {
    let i = memo;
    arr[i] = function(){
      console.log(i);
    }
    memo = i + 1;
  }
  arr.forEach(cb=>cb())

块级作用域中函数声明的方式
ES5中规定函数只能在顶层作用域和函数作用域中生成,不建议在块级作用域中使用函数声明的方式,而是采用函数表达式
块级作用是没有返回值的,如果想要块级作用域有返回值可以使用do{}
let本质上就是为了JS增加一个块级作用域

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值