(33)2021-02-24(ES6,ES6新增关键字let、const、块级作用域)

一、let

1.ES6简介

ECMA是一个标准 JavaScript是ECMAScript的实现。

ES6是ECMAScript的一个版本,是2015年发布的,也称ES2015.

2.let关键字

ES6新增的关键字,用来声明变量。用法类似于var,但是所声明的变量,只在let所在的代码块有效。

var a = [];
    for (var i = 0; i < 10; i++) {
       a[i] = function(){
           console.log(i);
       }
}
a[6](); //10

var定义的变量遇到for循环的大括号是不会形成作用域的。所以在上面代码调用时,调用的是一个全局的变量。

    var a = [];
    for (let i = 0; i < 10; i++) {
        a[i] = function () {
            console.log(i);
        }
    }
    a[6](); //6

以上代码中,i是使用let声明的,当前的i只在本轮的循环中有效。每一个循环中的i其实都是一个新的变量。所以输出的是6.

    for (let i = 0; i < 3; i++) {
       let i = "abc";
       console.log(i);
    }

结果:输出3次abc。

原因:在代码块中的变量i与for循环中的变量i不在用一个作用域。

2.1 不存在变量提升

var 存在变量提升。即变量在声明之前使用时,值为undefined。js会将声明语句放在所有js代码之前执行。

console.log(a);//undefined
var a = 10;
//相等于
var a;
console.log(a);
a = 10;
console.log(a);
let a = 10;

结果:提示错误Cannot access 'a' before initialization 译:在初始化之前无法访问“a”

2.2 暂时性死区
	var tmp = 123;
    if(true){
        tmp = "abc";
        let tmp;
        console.log(tmp);
    }

结果:提示错误Cannot access 'a' before initialization 译: 在初始化之前无法访问“a”

使用变量时,会先寻找同一作用域下的变量。以上代码中,tmp=abc会优先寻找到下面的let tmplet tmp不存在变量提升,所以提示错误。

总结:在代码块中,使用let命令声明变量之前,该变量都是不可用的状态,在语法上,称为“暂时性死区”

2.3 不允许重复声明

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

//Identifier 'a' has already been declared  标识符'a'已经声明
let a = "yasuo";
let a = "jianhao"  
console.log(a);
//Identifier 'a' has already been declared  标识符'a'已经声明
function show(a){
	let a = 10;
}
show(100);

以上代码中,函数的形参a与函数内部的a作用域相等,所以会报错。

正确写法:
	function show(a){
        {
            let a = 10;
        }
    }
    show(100);

3.块级作用域

3.1 为什么需要块级作用域

ES5 只有全局作用域和局部作用域(函数作用域),没有块级作用域。

缺点1:内部变量可能会覆盖外层的变量
var date = new Date();
function f(){
    console.log(date);
    if(false){
    	var date = "今天是个好日子"  
    }
}
f();//undefined

上面案例中,if代码块外部原意为使用外层的date,内部使用内部的date。但是函数执行后,结果却为undefined,原因是存在变量的提升。导致内部的date覆盖了外部的date变量

缺点2:for循环中的计数变量泄露为全局变量。
    var hello = "hello"
    
    for (var i = 0; i < hello.length; i++) {
       console.log(hello[i]);
    }
    console.log(i);

以上案例中,for·循环中的变量i只是用来作为计数使用,但是for循环执行完成后,它没有消失,而是作为全局变量仍然存在。以后可能不会再使用,造成资源的浪费。

3.2 ES6块级作用域
function show(){
        let a = "亚索";
        if(true){
            let a = "剑豪";
            {
                let a = "孤儿索"
            }
            console.log(a);
            
        }
        console.log(a);
    }
    show()

块级作用域下的变量不会对外层的变量造成影响,同时支持多层嵌套。

if(true)let  a = "亚索";
    
console.log(a);//报错

ES6的块级作用域必须有大括号,所以使用if判断时,不可以省略大括号。

4.案例

<ul>
    <li>诺手</li>
    <li>狼人</li>
    <li>亚索</li>
    <li>卡莎</li>
    <li>猫咪</li>
</ul>
	var lis = document.querySelectorAll("li");
	   //ES6之前的遍历点击事件的写法
        // for (var i = 0; i < lis.length; i++) {
        //     lis[i].dataset.index = i;
        //     lis[i].onclick = function(){
        //         alert(this.dataset.index);
        //     }
        // }

        //ES6遍历点击事件的写法
        for (let i = 0; i < lis.length; i++) {
            lis[i].onclick = function(){
                alert(i);
            }
        }

以上案例,使用let关键字实现点击li,弹出相对元素的下标。

二、const

1.基本用法

const也是用来声明变量的,不过它声明的是一个只读的常量。一旦声明,值不可修改。

const PI = 3.1415926;
// alert(PI);
PI = 3.14;
alert(PI);//  报错。Assignment to constant variable 为一个常量赋值了
1.2 必须初始化
const PI;
PI = 3.1415926;
alert(PI);
//报错.Missing initializer in const declaration  const声明中缺少初始化式

因为const声明的变量的值不可修改,所以,const一旦声明变量,则必须初始化。

1.3 一般变量名大写

规范。变量值为简单数据类型时,变量名一定要大写,如果为复合型数据类型(数组和对象)可以不大写。

1.4 也有块级作用域

constlet相同,只会在声明的所在代码块作用域内生效。

{const PI = 3.1415926;}
alert(PI);
//报错.PI is not defined
1.5 不存在变量提升
alert(PI);
const PI = 3.1415926;
//报错.
1.6 不可重复声明
 var PI = "3.14";
 const PI = 3.1415926;//报错.Identifier 'PI' has already been declared 译:标识符“PI”已经声明
1.7 对于数组和对象中的元素进行修改,不算对常量的改变

const变量保存的是:变量指向的值的内存地址。对于简单的数据(数值,字符串,布尔值),值保存在变量指向的内存地址。

对于复合数据类型,变量指向的内存地址,只是该对象的地址,其中的内容发生变化不会使该对象的内存地址发生变化。

const obj = {
	name:"亚索"
}
obj.name = "疾风剑豪";
console.log(obj.name);
//疾风剑豪
//错误写法
const obj = {
        name: "亚索",
 }
obj = {
        name: "孤儿索"
 }
 console.log(obj.name); //报错。Assignment to constant variable.译:为一个常量赋值了

三、例子

1.let

//1 --------------------------------------------
    // {
    //     var a = 1;
    //     let b = 2;
    //     console.log(b); //2
    // }

    //2 --------------------------------------------
    // {
    //     var a = 1;
    //     let b = 2;
    //     console.log(b); //2
    // }
    // console.log(a); //1
    // console.log(b); //b is not defined

    //3 --------------------------------------------
    // var a = [];
    // for (var i = 0; i < 10; i++) {
    //     a[i] = function() {
    //         console.log(i);
    //     }
    // }
    // a[6](); //10

    //4--------------------------------------------
    // for (var i = 0; i < 5; i++) {
    //     for (var i = 0; i < 5; i++) {
    //         console.log(i);//0 1 2 3 4
    //     }
    //     //两个for循环,相当于对i重新赋值。
    //    //var 碰到for循环的大括号,是不会形成作用域的。只会在函数中形成作用域。
    // }

    //5--------------------------------------------
    // var a = [];
    // for (let i = 0; i < 10; i++) {
    //     a[i] = function() {
    //         console.log(i);
    //     }
    // }
    // a[6]();//6

    //6--------------------------------------------
    // for (let i = 0; i < 5; i++) {
    //     for (let i = 0; i < 5; i++) {
    //         console.log(i);//0 1 2 3 4 会输出5轮,一共会输出25次,
    //     }
    // }

    //7--------------------------------------------
    // for (let i = 0; i < 3; i++) {
    //     let i = "abc";
    //     console.log(i);//会输出3次abc
    // }

    //8--------------------------------------------
    // let a = 100;
    // if (true) {
    //     let a = 1000;
    //     console.log(a); //1000
    // }
    // console.log(a); //100

    //9--------------------------------------------
    // console.log(a);
    // var a = 10; //undefined,var关键字:声明提升

    //10--------------------------------------------
    // console.log(a);
    // let a = 10;//报错,let关键字:不会声明提升

    //11--------------------------------------------
    // var temp = 123;
    // if (true) {
    //     temp = "abc"; //报错。暂时性死区:使用变量时,会先寻找同一作用域下的变量。`tmp=abc`会优先寻找到下面的`let tmp`而`let tmp`不存在变量提升,所以提示错误。
    //     let temp;
    //     console.log(temp);
    // }

    //12--------------------------------------------
    // let a = "yasuo";
    // let a = "jianhao";
    // console.log(a);

    // function show() {

    // }//报错。`let`不允许在相同的作用域中,重复声明同一个变量。

    //13--------------------------------------------
    // function show(a) {
    //     {
    //         let a = 10;
    //     }
    // }
    // show(100);//不会报错

    //14--------------------------------------------
    // var date = new Date();

    // function fn() {
    //     console.log(date);
    //     if (false) {
    //         var date = "今天是个好日子";
    //     }
    // }
    // fn();//undefined

    //15--------------------------------------------
    // var hello = "hello";
    // for (var i = 0; i < hello.length; i++) {
    //     console.log(hello[i]); //h e l l o
    // }

    //16--------------------------------------------
    // var hello = "hello";
    // for (var i = 0; i < hello.length; i++) {
    //     console.log(hello[i]); //h e l l o
    // }
    // console.log(i);//5  for循环中定义的i,是一个全局变量。仍然存在。资源浪费。

    //17--------------------------------------------
    // function show() {
    //     let a = "亚索";
    //     if (true) {
    //         let a = "剑豪"; {
    //             let a = "孤儿索";
    //         }
    //         console.log(a);
    //     }
    //     console.log(a);
    // }
    // show();//剑豪 亚索

    //18--------------------------------------------
    // if (true) let a = "亚索";
    // console.log(a); //报错

    //19--------------------------------------------
    if (true) var a = "亚索";
    console.log(a); //亚索

2.const

// const PI = 3.1415926;
        // alert(PI);
        // ----------------------------------

        // const PI = 3.1415926;
        // PI = 3.14;
        // alert(PI); //报错。Assignment to constant variable  译:为一个常量赋值了
        // -----------------------------------------------------

        // const PI;
        // PI = 3.1415926;
        // alert(PI);//报错。Missing initializer in const declaration  译:const声明中缺少初始化式
        // ---------------------------------------------

        // {
        //     const PI = 3.1415926;
        // }
        // alert(PI);//报错。PI is not defined
        // -------------------------------------------

        // var PI = "3.14";
        // const PI = 3.1415926;//报错。Identifier 'PI' has already been declared 译:标识符“PI”已经声明
        // ---------------------------------------

        // const obj = {
        //     name: "亚索",
        // }
        // obj.name = "疾风剑豪";
        // console.log(obj.name);//疾风剑豪
        // ---------------------------------------

        const obj = {
            name: "亚索",
        }
        obj = {
            name: "孤儿索"
        }
        console.log(obj.name); //报错。Assignment to constant variable.译:为一个常量赋值了
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值