ES6学习-let,块级作用域,const

文章参考:ECMAScript 6 入门-let 和 const 命令

let

let命令有四大主要特性:存在块级作用域没有变量提升暂时性死区不允许重复声明

1、存在块级作用域

  • let命令声明的变量只在其块级作用域中有效,就是{}中。
{
  let a = 10;
  var b = 1;
}
console.log(a); //出错 not defined
console.log(b); //1
  • es5中要实现块级作用域,通常借助立即执行匿名函数来实现,如下::
(function(){
 var a = 1;
}());
console.log(a); //出错,not defined
  • 但是有了let之后,我们可以使用{}直接实现,如下:
{
let a = 1;
}
console.log(a); //出错, not defined

2、没有变量提升

  • 我们在使用var进行变量定义时,会发生变量提升。即脚本开始运行时,变量a就已经存在,但是未被赋值,因此在赋值前输出时,则会输出undefined
console.log(a); //undefined
var a =1;

// 上述代码等价于
var a
console.log(a)
a = 1
  • 而使用let命令,则改变了该语法行为。使用let声明的变量不存在变量提升,因此变量必须在声明后使用,否则会报错,如下:
console.log(a); //出错, not defined
let a = 1;

3、暂时性死区

  • 在块级作用域内,若存在用let命令声明的变量,则所在区块对该变量形成封闭作用域,即该变量无视外部的同名变量。

而又因为不存在变量提升,因此在未使用let声明变量前,该变量都不可使用,其在语法上称为“暂时性死区”。

let a = 1;
if(true){ 
    a = 2; //出错 not defined
    let a; 
}
  • 对比var
var a = 1;
if(true){
    a = 2; //var允许重复声明,而且变量提升,故a=2正常赋值var a;
}
  • 暂时性死区的本质就是,只要一进入当前作用域,所要使用的变量就已经存在了,但是不可获取,只有等到声明变量的那一行代码出现,才可以获取和使用该变量。

4、不允许重复调用

  • let不可以在相同作用域内重复声明同一个变量,也包括不能和var,const变量名重复
{
  let a = 1;
  let a = 2;
} //出错 let不可重复声明

{
    var b = 1;
    let b = 1; 
} //出错 let不可重复声明

 
function func(arg) {
let arg;
}
func() // 报错

块级作用域

1、为什么需要块级作用域?

  • 在ES5中,只有全局作用域和函数作用域,不存在块级作用域,这就会导致如下问题的发生
  • 1)内层变量覆盖外层变量
  • 2)用于循环的计数变量会泄露为全局变量
  • 如下所示:
// 没有块级作用域,内层变量会覆盖外层变量
var time = new Date()
function fun (){
    console.log(time)
    if(false){
        var time = 'hello world'
    }
}
fun()

// 没有块级作用域,用来循环的计数变量会泄露为全局变量
var string = 'hello world'
for(var i=0;i<string.length;i++){
    console.log(string[i])
}
console.log('循环结束')
console.log(i)

2、ES6的块级作用域

  • 为了解决以上问题,ES6通过使用let为javascript 增加了块级作用域
function fun2 (){
  let num = 100
  if (true){
    let num = 200
  }
  console.log(num)
}
fun2()   // 100


for (let k=0;k<10;k++){
 console.log(k)
}
console.log('循环结束')
console.log(k)   // ReferenceError: k is not defined

3、ES6中块级作用域允许其任意嵌套,外层作用域无法读取内层作用域的变量

{{{{
    {let insane = 'Hello World'}
    console.log(insane); // 报错
}}}};

const

  • const  声明一个只读的常量。一旦声明,常量的值就不能改变。正是因为其值不能进行修改,因此, ,const一旦声明变量,就必须立即初始化,不能留到以后赋值。
  • const与let一样, 只在声明所在的块级作用域内有效
  • const命令声明的常量不存在提升
  • const命令声明的常量同样存在暂时性死区,只能在声明的位置后面使用。
  • const声明的常量,也与let一样不可重复声明
  • 本质:const实际上保证的,并不是变量的值不得改动,而是变量指向的那个内存地址所保存的数据不得改动。
        - 简单数据类型( 数值、字符串、布尔值): 值就保存在变量指向的那个内存地址,因此等同于常量
        - 复合数据类型( 对象和数组) : 变量指向的内存地址,保存的只是一个指向实际数据的指针 , const只能保证这个指针是固定的 至于它指向的数据结构是不是可变的,就完全不能控制了。因此,将一个对象声明为常量必须非常小心。
const arr = []
arr.push('hello wrold')  // 可执行
arr.length = 0     // 可执行
arr = ['hello everyone']  // arr is read-only

const person = {}
person.name = 'zhangsan'      // 可执行
console.log(person.name)      // zhangsan
person = {}  //person is read-only
  • 对象冻结:如果希望将一个对象进行冻结,可使用Object.freeze(),如下所示:
const person = Object.freeze({})
person.age = 30
person.name = 'zhangsan'
console.log(person.age)   // undefined
console.log(person.name)   // undefined
console.log(person)
  • 但上面的冻结方式只是将其对象本身冻结,其对象的属性也应该冻结,我们可以使用如下函数:
var constantize = (obj) => {
    Object.freeze(obj);
    Object.keys(obj).forEach( (key, i) => {
        if ( typeof obj[key] === 'object' ) {
            constantize( obj[key] );
        }
    });
};

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值