ES6的 let const 以及块级作用域

时间:2023-03-08 19:40:07
ES6的 let const  以及块级作用域

                              

                      let声明变量

用法类似于var,但是所声明的变量只在let所在的代码块内有效。

1 . 在ES6环境下,let声明的变量不能在声明之前调用。

例:  

console.log(i);  //会报错,这叫做暂时性死区,会提示 i 未定义

let i ;  

let不允许在变量还没声明完成前,赋值给其他变量,或者是自己

let a = a;  //报错

应该先声明,再赋值

let a ;

a = 1;

或者直接赋值

let a = 1;

var b = b;  //不会报错,但是会返回undefined,没有赋值

var a;  

2 . 在同级作用域中不能定义多个相同的 let 变量,在不同的作用域中,let 变量不会相互影响

let i = 1;

function foo(){

  let  i = 2;

  let  i = 3;

  console.log( i );

 //会报错,显示变量已经声明过了。

}

foo();

comsole.log( i )  //打印 1

3 . let变量只能在定义的作用域中使用,不能在该作用域之外调用,只要块级作用域存在let命令,它所声明的变量就绑定这个区域不再受外部影响

let s = 0;

var a = "我是外面的";

function li(){

  a = "我在里面了"

  let s = 1;

  let a = "我最大";

  function lon(){

    let s = 2;

    console.log(s);   //打印 2

}

  lon();

  console.log(s);  //打印  1

  console.log(a);   //打印 “ 我最大 ”

};

li();

4.若使用for循环let变量,let变量只在当前循环体内有效,在外面引用就会报错,每次循环时都会创建一个let变量,

js引擎会记住上一次循环的值。for循环设置循环变量的那部分是一个父作用域,而循环内部是一个单独的子作用域。

                              块级作用域

es6允许块级作用域任意嵌套,块作用域取代了立即执行函数(IIFE)不再必要了
{{{{
  let insst = '你好';
  {let insst = 'hello';}
  console.log(insst)//你好
}}}};

ES5中,函数只能在顶层作用域和函数作用域之中声明,不能在块级作用域中
声明
//es5中会得到"I am inside!",以为在 if 内声明的函数 f 会被提升到函数头部

function lis(){ console.log("123")};

  (function(){
  //es5中,lis方法会提升到这
    if(true){
      function lis(){ console.log("块作用域声明");}
    }
   lis();//显示 块作用域声明
  }());

lis();//显示的全局方法;

ES6允许在块级作用域中声明函数,块级作用域之中,函数声明语句的行为类似于
let,在块级作用域之外不可引用,但是如果真的在ES6浏览器中应用,还是会报错

function lis(){ console.log("123")};
  (function(){
    if(true){
      function lis(){ console.log("块作用域声明");}
    }
    lis();//显示块作用域
  }());

原因:如果改变了块级作用域内声明的函数的处理规则,显然会对老的代码产生
很大影响,为了减轻因此产生的不兼容问题,ES6规定,浏览器的实现可以不遵守
其规定,有自己的行为方式

1.允许在块级作用域内声明函数
2.函数声明类似于var,既会提升到全局作用域或函数作用域的头部
3.同时,函数声明还会提升到所在的块级作用域的头部

这三条规则只对ES6的浏览器有效,其他环境不用遵守,还是将块级作用域的函数
声明当做 let 处理

考虑到环境导致的行为差异太大,应该避免在块级作用域内声明函数,如果
确实需要,也应该写成函数表达式,而不是函数声明语句。

{ //不要使用这种
  let a = "in of itt";
  function f(){
    return a;
  }
}

{ //块级作用域内优先写成函数表达式
  let a = "in of itt";
  let f= function (){
    return a;
  }
}

ES6的块级作用域必须要有大括号,如果没有大括号js引擎就认为不存在块级作用域

if(true) let x = 1;//报错

  if(true){
    let x =1; //正确
}

                              const

const声明的叫做常量,与let的特性相差不多,不过除了有let的那些特性之外,它还有自己独立的特点;

const命令
声明一个只读的常量,一旦声明,常量的值就不能改变

const PI = 3.1415;
PI = 3 //会报错

const声明的常量不得改变值,这意味着const一旦声明常量,就必须立即初始化,
不能留到以后赋值。

const foo; //只声明不赋值,会报错
const的作用域与let命令相同:只在声明所在的块级作用域内有效。

详情解释:

const实际上保证的并不是变量的值不得改动,而是变量指向的那个内存地址所保存的数据
不得改动。对于简单的数据(数值,字符串,布尔值),值就保存在变量指向的那个
内存地址,因此等同于常量,但对于复合类型的数据(主要是对象和数组),变量指向
的内存地址,保存的只是一个指向实际数据的指针,const只能保证这个指针是固定的
(既总是指向另一个固定的地址),至于它指向的数据结构是不是可变的,就完全
不能控制了。

const foo = {};
//不报错
foo.lets = 3;
//上面的foo常量存储的是一个地址,这个地址指向一个对象,地址不能变,
//但是对象里面的属性可以变,所以依然可以为其添加新属性。

const foo = {};
//不报错
foo.lets = 3;
//上面的foo常量存储的是一个地址,这个地址指向一个对象,地址不能变,
//但是对象里面的属性可以变,所以依然可以为其添加新属性。
console.log(foo.lets);

const foo = [];
foo.push('Hello'); //使用方法添加,成功
foo.length //成功
foo = ['123'] //失败,不能直接为foo赋值数组
console.log(foo)

const foo = Object.freeze({});
//Object.freeze()
// 阻止对象的任何修改,比如:添加,删除,替换,以及对象的属性
//严格模式下会报错;
//常规模式下,下面一行没用
foo.prop = 123;
console.log(foo)

注:

今天在网上学到的,与大家共同分享,并且记录下来,如有错误,请指出,谢谢!