ES6入门(一)let与const

参考阮一峰的ECMAScript 6 入门

前言

ECMAScript 6.0(ES6)是JavaScript语言的下一代标准,在 2015 年 6 月正式发布。它的目标是使得 JavaScript 语言可以用来编写复杂的大型应用程序,成为企业级开发语言。

  1. ECMAScript与Javascript的关系
    ECMAScript是Javascript的规范,Javascript是ECMAScript的实现。
  2. ES6与ECMAScript 2015的关系
    ES6是ECMA的为JavaScript制定的第6个版本的标准,标准委员会最终决定,标准在每年的 6 月份正式发布一次,作为当年的正式版本。ECMAscript 2015 是在2015年6月份发布的ES6的第一个版本,ECMAscript 2016 是ES6的第二个版本。所以ES6 既是一个历史名词,也是一个泛指,含义是 5.1 版以后的 JavaScript 的下一代标准,涵盖了 ES2015、ES2016、ES2017 等等,而 ES2015 则是正式名称,特指该年发布的正式版本的语言标准。

一、let与const

ES6之前的作用域有全局作用域、函数作用域、eval作用域,ES6新增了块级作用域,用一对花括号来使用。

  1. ES6新增了let命令,用法类似于var,但是let所声明的变量只作用在当前块级作用域内

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

    可知,let声明的变量只在它所在的代码块有效。

  2. for循环很适合let命令

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

    变量i是var命令声明的,在全局范围内都有效,数组a的函数内部的console.log(i),使用的i是指向全局的i,是同一个i,这样在运行a[6]()输出的是循环之后的最后一轮值10。

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

    使用let声明的变量只在块级作用域即本轮循环有效,每一次循环i都是一个重新声明的变量。阮老师提到,JavaScript引擎内部会记住上一轮循环的值,初始化本轮的变量i时,就在上一轮循环的基础上进行计算。
    小题目:生成十个按钮,每个按钮点击的时候弹出1-10
    闭包实现:

    for(var i=1;i<=10;i++){
        (function(i){
            var btn = document.createElement('button');
            btn.innerText = i;
            btn.onclick = function(){
                alert(i);
            };
            document.body.appendChild(btn);
        })(i);
    }
    

    let命令实现:

    for(let i=1;i<=10;i++){
        var btn = document.createElement('button');
        btn.innerText = i;
        btn.onclick = function(){
            alert(i);
        };
        document.body.appendChild(btn);
    }
    

    这里出现了一个问题:报错 Uncaught TypeError: Cannot read property ‘appendChild’ of null ,原因是无法获取插入的节点。.js在head里面引入,在获取节点时,节点还没有加载,解决办法:.js改为在body里面引入

  3. let或者const不允许在相同作用域内重复声明一个变量

    let a = 10;
    let a = 12;
    // 'a' has already been declared
    
  4. let不存在变量提升

    console.log(a); // 输出undefined
    var a = 1;
    

    var命令会发生变量提升现象,在变量声明之前使用,值为undefined。为了纠正这种现象,规定let声明的变量一定要在声明后使用,否则报错。

    console.log(a); // 报错ReferenceError
    let a = 1;
    
  5. 暂时性死区

    var a = 1;
    {
        a = 2; // 报错ReferenceError
        let a = 3;
    }
    

    虽然存在全局变量a,但是在块级作用域内又声明了局部变量a,块级作用域对let(const)声明的变量从一开始就形成了封闭作用域,即使外部存在变量a也取不到它的值,同时又不能变量提升,就报错了。

  6. const声明一个常量,常量必须在声明的时候赋值,const与let有类似的特性。然而,常量为引用类型的时候,虽然不可改变变量的地址,但是可以修改该引用类型的值。

    const arr = [1];
    arr.push(2);
    console.log(arr);// 1,2
    arr = []; // 让arr指向一个新的数组,报错
    

    防止常量为引用类型的时候能被修改:

    const obj = {
        a: 1,
        b: 2
    };
    console.log(obj);// {a:1,b:2}
    Object.freeze(obj);
    obj.a = 3;
    console.log(obj);// {a:1,b:2}
    

    Object.freeze()方法接收一个参数,如果此参数是一个对象,则此方法把这个对象冻结,被冻结的对象不能修改、添加、删除其属性或者属性值

  7. ES6以前防止常量为引用类型的时候能被修改的做法

    var person = {
        name: 'Dell'
    };
    Object.defineProperty(person,'name',{
        // value: 'Dell',
        writable: false
    });
    Object.seal(person);
    

    Object.defineProperty() 方法会在一个对象上定义一个新属性,或者修改一个对象的现有属性, 并返回这个对象。它接收三个参数:要在其上定义属性的对象,要定义或修改的属性的名称,将被定义或修改的属性描述符。
    使用Object.seal()方法可以封闭一个对象,阻止添加新属性,并将所有现有属性标记为不可配置,已有属性的值如果原来是可写的,就可以改变。
    封装方法:(具体也不是很理解)

    Object.defineProperty(Object,'freezePolyfill',{
        value: function(obj){
            for(var i in obj){//遍历属性和方法
                if(obj.hasOwnProperty(i)){
                	// 修改遍历到的属性描述
                    Object.defineProperty(obj,i,{
                        writable: false
                    });
                }
                // 使用Object.seal()方法封闭对象
                Object.seal(obj);
            }
        }
    });
    const person = {
        name: 'Dell'
    };
    Object.freezePolyfill(person);
    

    使用hasOwnProperty()方法,在给定属性存在于对象实例中时返回true,保证属性是来自实例而不是原型。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值