七、ES6-JavaScript核心内容精讲

七、ES6

从这一章节开始,我们来看一下关于ES6的重点内容。

1、let 关键字

1.1 基本用法

ES6中新增了let命令,用于变量的声明,基本的用法和var类似。例如:

<script>
  // 使用var使用声明变量
  var userName = "bxg";
  console.log("userName=", userName);
  // 使用let声明变量
  let userAge = 18;
  console.log("userAge=", userAge);
    </script>

通过以上的代码,我们发现var和let的基本使用是类似的,但是两者还是有本质的区别,最大的区别就是:

使用let所声明的变量只在let命令所在的代码块中有效。

1.2 let与var区别

下面我们通过一个for循环的案例来演示一下let和var的区别,如下所示:

<script>
  for (var i = 1; i <= 10; i++) {
     
    console.log("i=", i)
  }
  console.log("last=", i)
    </script>

通过以上的代码,我们知道在循环体中i的值输出的是1–10,最后i的值为11.

但是如果将var换成let会出现什么问题呢?代码如下:

   for (let i = 1; i <= 10; i++) {
   
            console.log("i=", i)
        }
        console.log("last=", i)

在循环体中输出的i的值还是1–10,但是循环体外部打印i的值时出现了错误,错误如下:

let关键字.png

出错的原因是:通过let声明的变量只在其对应的代码块中起作用,所谓的代码块我们可以理解成就是循环中的这一对大括号。

当然在这里我们通过这个提示信息,可以发现在ES6中默认是启动了严格模式的,严格模式的特征就是:变量未声明不能使用,否则报的错误就是变量未定义。

那么在ES5中怎样开启严格模式呢?我们可以在代码的最开始加上:“use strict”

刚才我们说到,let声明的变量只在代码块中起作用,其实就是说明了通过let声明的变量仅在块级作用域内有效

1.3 块级作用域

1.3.1 什么是块级作用域?
	在这里告诉大家一个最简单的方法: **有一段代码是用大括号包裹起来的,那么大括号里面就是一个块级作用域**

也就是说,在我们写的如下的案例中:

   for (let i = 1; i <= 10; i++) {
   
            console.log("i=", i)
        }
        console.log("last=", i)

i 这个变量的作用域只在这一对大括号内有效,超出这一对大括号就无效了。

1.3.2  为什么需要块级作用域?
	ES5 只有全局作用域和函数作用域,没有块级作用域,这样就会带来一些问题,
	第一:内层变量可能会覆盖外层变量

代码如下:

	  var temp = new Date();
        function show() {
   
            console.log("temp=", temp)
            if (false) {
   
                var temp = "hello world";
            }
        }
        show();

执行上面的代码,输出的结果为 temp=undefined  ,原因就是变量由于提升导致内层的temp变量覆盖了外层的temp变量

	第二: 用来计数的循环变量成为了全局变量

	关于这一点,在前面的循环案例中,已经能够看到。在这里,可以再看一下
<script>
  for (var i = 1; i <= 10; i++) {
     
    console.log("i=", i)
  }
  console.log("last=", i)
    </script>

在上面的代码中,变量i的作用只是用来控制循环,但是循环结束后,它并没有消失,而是成了全局的变量,这不是我们希望的,我们希望在循环结束后,该变量就要消失。

以上两点就是,在没有块级作用域的时候,带来的问题。

下面使用let来改造前面的案例。

 	let temp = new Date();
        function show() {
   
            console.log("temp=", temp)
            if (false) {
   
                let temp = "hello world";
            }

        }
        show();

通过上面的代码,可以知道let不像var那样会发生“变量提升”的现象。

第二个问题前面已经讲解过。

1.3.3 ES6块级作用域

let实际上为JavaScript新增了块级作用域,下面再看几个案例,通过这几个案例,巩固一下关于“块级作用域”这个知识点的理解,同时进一步体会块级作用域带来的好处

<script>
  function test() {
     
    let num = 5;
    if (true) {
     
      let num = 10;
    }
    console.log(num)
  }
  test()
    </script>

上面的函数中有两个代码块,都声明了变量num,但是输出的结果是5.这表示外层的代码不受内层代码块的影响。如果使用var定义变量num,最后的输出的值就是10.

说一下,下面程序的输出结果是多少?

if (true) {
   
            let b = 20;
            console.log(b)
            if (true) {
   
                let c = 30;
            }
            console.log(c);
        }

输出的结果是:b的值是20,在输出c的时候,出现了错误。

导致的原因,两个if就是两个块级作用域,c这个变量在第二个if中,也就是第二个块级作用域中,所以在外部块级作用域中无法获取到变量c.

块级作用域的出现,带来了一个好处以前获得广泛使用的立即执行匿名函数不再需要了。

下面首先定义了一个立即执行匿名函数:

   ;(function text() {
   
            var temp = 'hello world';
            console.log('temp=', temp);
        })()

匿名函数的好处:通过定义一个匿名函数,创建了一个新的函数作用域,相当于创建了一个“私有”的空间,该空间内的变量和方法,不会破坏污染全局的空间 。

但是以上的写法是比较麻烦的,有了“块级作用域”后就编的比较简单了,代码如下:

   		{
   
            let temp = 'hello world';
            console.log('temp=', temp);
        }

通过以上的写法,也是创建了一个“私有”的空间,也就是创建了一个封闭的作用域。同样在该封闭的作用域中的变量和方法,不会破坏污染全局的空间。

但是以上写法比立即执行匿名函数简单很多。

现在问你一个问题,以下代码是否可以:

	let temp = '你好';
        {
   
             let temp = 'hello world';
        }

答案是可以的,因为这里有两个“块级作用域”,一个是外层,一个是内层,互不影响。

但是,现在修改成如下的写法:

   	  let temp = '你好';
         {
   
            console.log('temp=', temp);
            let temp = 'hello world';
        }

出错了,也是变量未定义的错误,造成错误的原因还是前面所讲解的let 不存在“变量提升”。

块级作用域还带来了另外一个好处,我们通过以下的案例来体会一下:

该案例希望不同时间打印变量i的值。

      for (var i = 0; i < 3; i++) {
   
                setTimeout(function() {
   
                    console.log('i=', i);
                }, 1000)
        }

那么上面程序的执行结果是多少?

对了,输出的都是 i=3

造成的原因就是i为全局的。

那么可以怎样解决呢?相信这一点对你来说很简单,在前面ES5课程中也讲过。

  for (var i = 0; i < 3; i++) {
   
            (function(i) {
   
                setTimeout(function() {
   
                    console.log('i=', i);
                }, 1000)
            })(i)
        }

通过以上的代码其实就是通过自定义一个函数,生成了函数的作用域,i变量就不是全局的了。

这种使用方式很麻烦,有了let命令后,就变的非常的简单了。

代码如下:

  for (let i = 0; i < 3; i++) {
   
            setTimeout(function() {
   
                console.log('i=', i);
            }, 1000)
        }

1.4 let命令注意事项

1.4.1 不存在变量提升

let不像var那样会发生“变量提升”现象。所以,变量一定要在声明后使用,否则会出错。

关于这一点,前面的课程也多次强调。

  console.log(num);
  let num = 2;
1.4.2 暂时性死区

什么是暂时性死区呢?

先来看一个案例:

	 var num = 123;
        if (true) {
   
            num = 666;
            let num;
        }

上面的代码中存在全局的变量num,但是在块级作用域内使用了let又声明了一个局部的变量num,导致后面的num绑定到这个块级作用域,所以在let声明变量前,对num进行赋值操作会出错。

所以说,只要在块级作用域中存在let命令,它所声明的变量就被“绑定”在这个区域中,不会再受外部的影响。

关于这一点,ES6明确规定,如果在区域中存在let命令,那么在这个区域中通过let命令所声明的变量从一开始就生成了一个封闭的作用域,只要在声明变量前使用,就会出错

所以说,所谓的“暂时性死区”指的就是,在代码块内,使用let命令声明变量之前,该变量都是不可用的。

1.4.3  不允许重复声明

let 不允许在相同的作用域内重复声明一个变量,

如果使用var声明变量是没有这个限制的。

如下面代码所示:

function test() {
   
            var num = 12;
            var num = 20;
            console.log(num)
        }
        test()

以上代码没有问题,但是如果将var换成let,就会出错。如下代码所示:

 function test() {
   
            let num = 12;
            let num = 20;
            console.log(num)
        }
        test()

当然,以下的写法也是错误的。

  function test() {
   
            var num = 12;
            let num = 20;
            console.log(num)
        }
        test()

同时,还需要注意,不能在函数内部声明的变量与参数同名,如下所示:

   function test(num) {
   
            let num = 20;
            console.log(num)
        }
        test(30)

2、const命令

2.1 基本用法

const用来声明常量,常量指的就是一旦声明,其值是不能被修改的。

这一点与变量是不一样的,而变量指的是在程序运行中,是可以改变的量。

		let num = 12;
        num = 30;
        console.log(num)

以上的代码输出结果为:30

但是通过const命令声明的常量,其值是不允许被修改的。

        const PI = 3.14;
        PI = 3.15;
        console.log(PI)

以上代码会出错。

在以后的编程中,如果确定某个值后期不需要更改,就可以定义成常量,例如:PI,它的取值就是3.14,后面不会改变。所以可以将其定义为常量。

2.2 const命令注意事项

2.2.1 不存在常量提升

以下代码是错误的

        console.log(PI);
        const PI = 3.14
2.2.2 只在声明的块级作用域内有效

const命令的作用域与let命令相同:只在声明的块级作用域内有效

如下代码所示:

        if (true) {
   
            const PI = 3.14;
        }
        console.log(PI);

以上代码会出错

2.2.3 暂时性死区

const命令与let指令一样,都有暂时性死区的问题,如下代码所示:

        if (true) {
   
            console.log(PI);
            const PI = 3.14;
        }

以上代码会出错

2.2.4 不允许重复声明
        let PI = 3.14;
        const PI = 3.14;
        console.log(PI);

以上代码会出错

2.2.5 常量声明必须赋值

使用const声明常量,必须立即进行初始化赋值,不能后面进行赋值。

如下代码所示:

        const PI;
        PI = 3.14;
        console.log(PI);

以上代码会出错

3、解构赋值

3.1、数组解构赋值基本用法

所谓的解构赋值,就是从数组或者是对象中提取出对应的值,然后将提取的值赋值给变量。

首先通过一个案例,来看一下以前是怎样实现的。

 	 	let arr = [1, 2, 3];
        let num1 = arr[0];
        let num2 = arr[1];
        let num3 = arr[2];
        console.log(num1, num2, num3);

在这里定义了一个数组arr,并且进行了初始化,下面紧跟着通过下标的方式获取数组中的值,然后赋值给对应的变量。

虽然这种方式可以实现,但是相对来说比较麻烦,ES6中提供了解构赋值的方式,代码如下:

        let arr = [1, 2, 3];
        let [num1, num2, num3] = arr;
        console.log(num1, num2, num3);

将arr数组中的值取出来分别赋值给了,num1,num2和num3.

通过观察,发现解构赋值等号两侧的结构是类似。

下面再看一个案例:

 let arr = [{
   
                userName: 'zs',
                age: 18
            },
            [1, 3], 6
        ];
        let [{
   
                userName,
                age
            },
            [num1, num2], num3
        ] = arr;
        console.log(userName, age, num1, num2, num3);

定义了一个arr数组,并且进行了初始化,arr数组中有对象,数组和数值。

现在通过解构赋值的方式,将数组中的值取出来赋给对应的变量,所以等号左侧的结构和数组arr的结构是一样的。

但是,如果不想获取具体的值,而是获取arr数组存储的json对象,数组,那么应该怎样写呢?

  let arr = [{
   
                userName: 'zs',
                age: 18
            },
            [1, 3], 6
        ];
        let [jsonResult, array, num] = arr;
        console.log(jsonResult, array, num);

3.2、注意事项

3.2.1  如果解析不成功,对应的值会为undefined.
        let [num1, num2] = [6]
        console.log(num1, num2);

以上的代码中,num1的值为6,num2的值为undefined.

3.2.2  不完全解构的情况

所谓的不完全解构,表示等号左边只匹配右边数组的一部分。

代码如下:

        let [num1, num2] = [1, 2, 3];
        console.log(num1, num2);

以上代码的执行结果:num1=1,num2 = 2

也就是只取了数组中的前两个值。

        // 如果只取第一个值呢?
       let [num1] = [1, 2, 3];
	  console.log(num1);
        //只取第二个值呢?
        let [, num, ] = [1, 2, 3];
        console.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值