ECMAScript6新特性(一)

来源:互联网 发布:修改tomcat的端口号 编辑:程序博客网 时间:2024/05/18 18:00

新特性概览

参考文章: http://www.cnblogs.com/Wayou/p/es6_new_features.html

—————————————————————————————————————————————————————————

ES6测试引入文件

<<bootstrap.js>>

<<traceur.js>>

—————————————————————————————————————————————————————————

let命令

  • let命令用来声明变量,用法类似于var,但仅仅可以使用在定义的代码块中
  • 不存在变量提升
  • 暂时性死区:只要块级作用域内存在let命令,它所声明的变量就”绑定”binding这个区域,不再受外部影响
  • 不允许重复声明:let不允许在相同作用域内重复声明同一个变量

样例

<<test.js>>

复制代码
// 在该代码块中声明let,外部不能调用,花括号之内{    let a = 100;    var b = 200;}// console.log(a);// 在这里var进行了变量提升,可以在全局中使用,let不可以变量提升console.log(b);// ********************************************************************// 不存在变量提升// ES5var arr = [],    arrTest = [];// 在循环中c并没有赋给数组,而是被i循环覆盖为9,所以输出的都是9for (var i = 0; i < 10; i++) {    var c = i;    arr[i] = function() {        return c;    }}// 遍历执行for (var i = 0; i < 10; i++) {    arrTest[i] = arr[i]();}console.log(arrTest);// ES6var arr2 = [];// var c → let dfor (var i = 0; i < 10; i++) {    let d = i;    arr2[i] = function() {        return d;    }}for (var i = 0; i < 10; i++) {    arrTest[i] = arr2[i]();}console.log(arrTest);// 教学视频中没有说清楚,那么是否是因为let d 只对对应的代码块起作用,出现了10个不同的d呢?// ********************************************************************// 暂时性死区{    console.log(e);    let e = 100;    console.log(e);}// 在视频中得到的结果是undefined和100,而在我的测试中第一个console.log得到的是报错信息,提示未定义// 在该代码块中let管辖着e,当未声明变量e时,打印e则会提示未定义的,暂时不可以使用的// ********************************************************************// 不允许重复声明{    var f = 1;    let f = 100;}{    let g = 100;    var g = 1;}// 重复声明会产生报错信息Identifier 'f' has already been declared
复制代码

<<index.html>>

复制代码
<!DOCTYPE html><html><head>    <meta charset="utf-8">    <script src="traceur.js"></script>    <script src="bootstrap.js"></script>    <script type="text/javascript" src="test.js"></script></head><body></body></html>
复制代码

—————————————————————————————————————————————————————————

块级作用域

let实际上为JavaScript新增了块级作用域

  • ES5中只有全局作用域和函数作用域,没有块级作用域,容易出现以下问题:
    • 内层变量可能会覆盖外层变量
    • 用来计数的循环变量泄露为全局变量

<<index.html>>

复制代码
<!DOCTYPE html><html><head>    <meta charset="utf-8">    <script src="traceur.js"></script>    <script src="bootstrap.js"></script>    <!-- ES5 -->    <script type="text/javascript">    var time = new Date();    function f1() {        console.log(time);        if (false) {            var time = 'hello'; // 变量重复声明了之后,内部time会覆盖已有变量的内存地址,在运行时console.log会寻找地址,此时地址还没有存入值'hello',所以输出为undefined            // time ='hello'; // 如果是使用赋值语句,则正常输出time为Date();        }    }    f1();    // ****************************************    // 循环变量泄露为全局变量的问题    for (var i = 0; i < 12; i++) {}    // i跳出了循环体,循环结束后i没有被销毁    console.log(i);    // 在其他函数中也会被使用    function f2() {        console.log(i);    }    f2();    // ****************************************    // Demo1:    // 第二次声明nTest1会覆盖第一次声明,得到200的值    function f3() {        var nTest1 = 100;        if (true) {            var nTest1 = 200;        }        console.log(nTest1);    }    f3();    // ****************************************    // Demo2:自调用函数    // 视频演示中ES5得到的是inside,ES6得到的是outside    // 测试时ES5报错,ES6正常inside    function fun(){        console.log('i am outside');    };    (function (){        if (false) {            function fun(){                console.log("i am inside");            };        }        fun();    })();    </script>    <!-- ES6 -->    <script type="text/traceur">    // ****************************************    // Demo1:        function f4() {            let nTest2 = 100;            if (true) {                let nTest2 = 200;                console.log(nTest2);            }            console.log(nTest2);        }        f4();    // ****************************************    // Demo2:自调用函数    function fun(){        console.log('i am outside');    }    (function (){        if (false) {            function fun(){                console.log("i am inside");            }        }        fun();    }())    </script></head><body></body></html>
复制代码

—————————————————————————————————————————————————————————

const命令

const关键字声明的是常量,不可改变

<<index.html>>

复制代码
<!DOCTYPE html><html><head>    <meta charset="utf-8">    <script src="traceur.js"></script>    <script src="bootstrap.js"></script>    <!-- ES5 -->    <script type="text/javascript">        // const命令        const Pi = 3.1415;        console.log(Pi);        // 赋值的话返回错误信息Assignment to constant variable.        // Pi = 1;        // ***********************************************************        // const的块级作用域问题        if (true) {            var a = 1;        }        // Error: a is not defined        // 可见const关键字定义的也有块级作用域的问题        // console.log(a);    </script>    <!-- ES6 -->    <script type="text/traceur">        // 暂时性死区        if (true) {            console.log(b);            const b = 2;        }        // ***********************************************************        {            //Error:["file:///F:/6.Code/Front-End/JavaScript/Test/index_inline_script_1.js:6:16: Duplicate declaration, c"]            //不可重复声明            //var c=200;            const c = 300;            console.log(c);        }        // ***********************************************************        // 通过const声明对象时,显示这个对象是只读的,该对象是冻结状态的,但仍然可以写入值        const person = {};        person.name = "hello";        console.log(person);        person.name = "hugh";        console.log(person);        console.log(Object.isSealed());        console.log(Object.isFrozen());        // 如果以冻结方法定义的对象,则是无法写入的        const person2 = Object.freeze({});        person2.name = "hugh";        person2.age = 21;        console.log(person2);        console.log(person2.name);        console.log(person2.age);        console.log(Object.isFrozen());        // 正确的const冻结对象的方法        const person3 = Object.freeze({            name: 'hhh',            age: 1        });        console.log(person3);        console.log(Object.isFrozen());        // ***********************************************************        // const声明的数组可以数组操作,但不可以整体赋值,视为重新定义        const arr1 = [];        arr1.push(1);        arr1.push(2);        console.log(arr1);        arr1.pop();        console.log(arr1);        console.log(arr1.length);        //Error:["file:///F:/6.Code/Front-End/JavaScript/Test/index_inline_script_1.js:30:5: arr1 is read-only"]        //arr1 = ['a','b','c'];        //console.log(arr1);        // ***********************************************************        // 彻底冻结对象,请对比参考JavaScript中的递归冻结函数方法        var constantize = (obj) => {            Object.freeze(obj);            Object.keys(obj).forEach((key,value)=>{                if(typeof obj[key]==='object'{                    constantize(obj[key]);                });            });        };    </script></head><body></body></html>
复制代码

—————————————————————————————————————————————————————————

跨模块常量

<<index.html>>

复制代码
<!DOCTYPE html><html><head>    <meta charset="utf-8">    <script src="traceur.js"></script>    <script src="bootstrap.js"></script>    <!-- ES5 -->    <script type="text/javascript">    </script>    <!-- ES6 -->    <script type="text/traceur">    // module.js, 在这里将变量输出    export const cVariantName = "111";    export const iVariantName = 3;    export const fVariantName = 4.111;    // use.js, 在这里将变量全部引入    import * as variant from './module.js';    console.log(variant.cVariantName); // 输出"111";    console.log(variant.iVariantName); // 输出3;    console.log(variant.fVariantName); // 输出4.111;    // otherUse.js, 引入部分变量    import {iVariantName,fVariantName} as variant from './module.js';    console.log(variant.iVariantName); // 输出3;    console.log(variant.fVariantName); // 输出4.111;    // onlyUse.js, 只引入一个变量    import iVariantName as variant from './module.js';    console.log(variant.iVariantName); // 输出3;    </script></head><body></body></html>
复制代码

—————————————————————————————————————————————————————————

全局对象属性

  • 全局变量是最顶层的对象
  • 浏览器环境指的是window对象
  • Node.js指的是global对象
  • JavaScript中所有全局变量都是全局对象的属性

    p.s.Node中这一条只对REPL环境使用,模块环境必须显式声明成global属性

  • ES6规定:
    • varfunction命令声明的全局变量,属于全局对象的属性
    • letconstclass命令声明的全局变量,不属于全局对象的属性

<<index.html>>

复制代码
<!DOCTYPE html><html><head>    <meta charset="utf-8">    <script src="traceur.js"></script>    <script src="bootstrap.js"></script>    <!-- ES5 -->    <script type="text/javascript">    </script>    <!-- ES6 -->    <script type="text/traceur">    var varName = "varValue";    // 浏览器环境    console.log(window.varName); // 输出varValue    // Node环境    // console.log(global.varName);    // 通用环境    console.log(this.varName); // 输出varValue    let letName = "letValue";    console.log(window.letName); // 兼容模式:letValue, 严格模式:undefined    console.log(this.letName); // 兼容模式:letValue, 严格模式:undefined    </script></head><body></body></html>
复制代码

—————————————————————————————————————————————————————————

解构赋值 Dustructuring

  • 解构:ES6允许按照一定模式,从数组和对象中提取值,对变量进行赋值
  • 不完全解构:等号左边的模式只匹配一部分等号右边的数组
  • 指定默认值:ES6内部使用严格相等运算符===来判断一个位置是否有值,如果数组成员不严格等于undefined默认值不会生效
  • letconst命令:只要某种数据结构具有iterator(迭代器)接口,都可以采用数组形式解构赋值

数组解构赋值

<<index.html>>

复制代码
<!DOCTYPE html><html><head>    <meta charset="utf-8">    <script src="traceur.js"></script>    <script src="bootstrap.js"></script>    <!-- ES5 -->    <script type="text/javascript">    // Set对象    var s = new Set();    s.add("Thomas Jefferson");    s.add(1776);    s.add("founding father");    s.forEach(function (item) {        console.log(item.toString() + ", ");    });    </script>    <!-- ES6 -->    <script type="text/traceur">    //数组解构    // 通过这种形式批量结构赋值    var [a,b,c] = [1,2,3];    console.log(a);    console.log(b);    console.log(c);    // 对应位置数组解构    let [foo,[[bar],,base]] = [1,[[2],3,4]];    console.log(foo);    console.log(bar);    console.log(base);    // ...tail 作为数组    let [head, ...tail] = [0,1,2,3,4,5,6,7,8,9];    console.log(head);    console.log(tail);    // 不完全解构    let [x,y] = [1,2,3];    console.log(x);    console.log(y);    let [x1,y1] = [100];    console.log(x1); // 100    console.log(y1); // undefined    // 指定默认值    var [temp = 'string'] = []; // 在这里temp的默认值为string,如果不给值的话为默认string    console.log(temp);    var [temp1 = 'string1'] = ['string2'];    console.log(temp1);    var [temp2 = 'aaa',temp3] = ['bbb'];     console.log(temp2); // 'bbb'    console.log(temp3); // undefined, 解构时完全对应给定值,bbb赋值给temp2,没有值给tmep3,参见不完全解构    var [temp4 = 'aaa'] = [undefined];    console.log(temp4); // 'aaa' 因为给定的值是未定义的    // 非遍历结构 - 报错    // var [temp5] = 1; // traceur.js:31513 TypeError: 1[Symbol.iterator] is not a function    // 迭代器    let [a1,b1,c1] = new Set(['aaa','bbb','ccc']);    console.log(a1);    console.log(b1);    console.log(c1);    function* fibs(){        let a2 = 0;        let b2 = 1;        while(true){            yield a2;            [a2,b2] = [b2,a2+b2];        }    }    var [first,second,third,fourth,fifth,sixth] = fibs();    console.log(first);    console.log(second);    console.log(third);    console.log(fourth);    console.log(fifth);    console.log(sixth);    </script></head><body></body></html>
复制代码

对象解构赋值

<<index.html>>

复制代码
<!DOCTYPE html><html><head>    <meta charset="utf-8">    <script src="traceur.js"></script>    <script src="bootstrap.js"></script>    <!-- ES5 -->    <script type="text/javascript">    </script>    <!-- ES6 -->    <script type="text/traceur">    // 对象解构赋值    var {name,age,id} = {id:'0001',name:'hugh',age:20};    console.log(name);    console.log(age);    console.log(id); // 可以不按顺序    // 变量名和属性名不一致    var {change_name,age,id} = {id:'0001',name:'hugh',age:20};    console.log(change_name); // undefined    // 将变量名和属性名对应起来    var {name:person_name,age:person_age,id:person_id} = {id:'0001',name:'hugh',age:20};    console.log(person_id);    console.log(person_name);    console.log(person_age);    // 重构对象    let object = {first:1,second:2};    let {first:first_num , second:second_num} = object; // 结构对象    console.log(first_num);    console.log(second_num);    // 指定默认值    // 结构默认值的条件为 === undefined    var {x = 3,y = 5} = {};    console.log(x);    console.log(y);    var {massage:msg = "yes!"} = {};    console.log(msg);    // 已声明变量的解构赋值    var test;    // {test} = {test:1};    ({test} = {test:1});    console.log(test);    // 现有对象的方法    let {sin,cos,tan} = Math;    console.log(sin(Math.PI/6));    </script></head><body></body></html>
复制代码

字符串解构赋值

<<index.html>>

复制代码
<!DOCTYPE html><html><head>    <meta charset="utf-8">    <script src="traceur.js"></script>    <script src="bootstrap.js"></script>    <!-- ES5 -->    <script type="text/javascript">    </script>    <!-- ES6 -->    <script type="text/traceur">    // 字符串的解构赋值    const [a,b,c,d,e,f] = "hello!"; // 逐位对应解构赋值    console.log(a);    console.log(b);    console.log(c);    console.log(d);    console.log(e);    console.log(f);    // 字符串的length属性解构    const {length : len} = "hhh"; // 通过对象取属性    console.log(len);    const {length} = "1111";    console.log(length);    </script></head><body></body></html>
复制代码

函数参数解构赋值

<<index.html>>

复制代码
<!DOCTYPE html><html><head>    <meta charset="utf-8">    <script src="traceur.js"></script>    <script src="bootstrap.js"></script>    <!-- ES5 -->    <script type="text/javascript">    </script>    <!-- ES6 -->    <script type="text/traceur">    // 函数参数的解构赋值    function sum ([x, y]){        return x + y;    }    console.log(sum([1, 2])); // 解构赋值传入一个数组,数组变量解构赋值    // 函数参数解构默认值    // 在这里0和1并不是赋值操作,而是声明变量,所以不能使用以下这种方法:function fun({x, y} = {x : 0, y : 1}),将{x, y} = {x : 0, y : 1}作为函数内部的语句来操作,如果传入的是fun(),return 0 0,传入fun({x:100}),return 100 undefined    function fun({x = 0, y = 1} = {}){         return [x, y];    }    console.log(fun({x : 100})); // y返回的是默认值    console.log(fun()); // x,y均返回默认值    </script></head><body></body></html>
复制代码

解构赋值用途

  • 交换变量的值
  • 从函数返回多个值
  • 函数参数的定义
  • 提取Json数据
  • 函数参数的默认值
  • 遍历Map结构
  • 输入模块的指定方法

<<index.html>>

复制代码
<!DOCTYPE html><html><head>    <meta charset="utf-8">    <script src="traceur.js"></script>    <script src="bootstrap.js"></script>    <!-- ES5 -->    <script type="text/javascript">    </script>    <!-- ES6 -->    <script type="text/traceur">    // 交换变量的值    // ES5中通过temp变量, temp = a; a = b; b = temp;    var x = 100, y = 200;    [x, y] = [y, x];    console.log([x, y]);    // ************************************************************************************    // 从函数返回多个值,优势:不需要使用fun.id之类的操作,直接取值到变量    // 返回一个数组    function fun(){        return [1, 2, 3];    }    var [x, y, z] = fun();    console.log(x);    console.log(y);    console.log(z);    // 返回一个对象    function fun1(){        return {            id : "0001",            name : "hugh",            age : 20        };    }    var {id : person_id, name : person_name, age : person_age} = fun1();    console.log(person_id);    console.log(person_name);    console.log(person_age);    // ************************************************************************************    // 函数参数的定义    // 参数有次序    function fun2([x, y, z]){        console.log(x);        console.log(y);        console.log(z);    }    fun2([1, 2, 3]);    // 参数无次序    // 使用到的是对象的解构赋值,用于接口的交互,如果是使用AJAX交互时,没必要在传值前打包,直接封装成Json对象,打包好传过来,可以使整个模块更清晰    function fun3({id, name, age}){        console.log(id);        console.log(name);        console.log(age);    }    fun3({name : "dong", id : '0002', age : 30});    // ************************************************************************************    // 提取Json数据    var jsonData = {        id : "0003",        name : "dong",        age : 21,        score : {            Chinese : 99,            Math : 98,            English : 97        }    };    // 通常情况下提取Json数据    console.log(jsonData);    console.log("id:"+jsonData.id);    console.log("name:"+jsonData.name);    console.log("chinese score:"+jsonData.score.Chinese);    console.log("english score:"+jsonData.score.English);    // ES6下解构后    let {id:number, xingming, age, score:chengji} = jsonData;    console.log("ES6:"+number);    console.log("ES6:"+xingming);    console.log("ES6:"+age);    console.log("ES6:"+chengji.Chinese);    // ************************************************************************************    // 函数参数的默认值    // 内建的ajax    // jQuery.ajax({    //     url :'/path/to/file',    //     type :'POST',    //     dataType : 'xml/html/script/json/jsonp',    //     data : {param1 : 'value1'},    //     complate : function(xhr, textStatus){    //         // called when complete    //     },    //     success : function(data, textStatus, xhr){    //         // called when success    //     },    //     error : function(xhr, textStatus, errorThrown){    //         // called when there is an error      //     }    // });    // 解构赋值方式,通过参数的默认值来进行ajax运算,突出函数的传值    // 避免了在函数体内部再写 var foo = config.foo || 'default foo'; 这样的语句    // jQuery.ajax = function (url, {    //     async = true,    //     beforeSend = function (){},    //     cache = true,    //     complete = function (){},    //     crossDomain = false,    //     global = true,    //     // ...more config    // }){    //     // ...do stuff    // };    // ************************************************************************************    // 遍历Map解构    var map = new Map();    map.set("id","0007"); // 创建键值对    map.set("name","hehe");    console.log(map); // map结构是object    for(let [key, value] of map){ // 遍历获取键值对        console.log(key + " is " + value);    }    for (let[key] of map){ // 遍历获取键名        console.log(key);    }    for (let [, value] of map){ // 遍历获取键值, p.s. [ , value] !!!        console.log(value);    }     // ************************************************************************************    // 输入模块的指定方法    const { SourceMapConsumer , SourceNode } = require("source-map");    </script></head><body></body></html>
复制代码

分类: 前端
好文要顶 关注我 收藏该文
hugh.dong
关注 - 26
粉丝 - 8
+加关注
0
0

« 上一篇:H5 Canvas | 画布中变量作用域与setInterval方法同步执行探究
    </div>    <div class="postDesc">posted @ <span id="post-date">2017-07-28 13:02</span> <a href="http://www.cnblogs.com/hughdong/">hugh.dong</a> 阅读(<span id="post_view_count">9</span>) 评论(<span id="post_comment_count">0</span>)  <a href="https://i.cnblogs.com/EditPosts.aspx?postid=7249667" rel="nofollow">编辑</a> <a href="#" onclick="AddToWz(7249667);return false;">收藏</a></div></div><script type="text/javascript">var allowComments=true,cb_blogId=348463,cb_entryId=7249667,cb_blogApp=currentBlogApp,cb_blogUserGuid='091e0fa5-3c20-e711-9fc1-ac853d9f53cc',cb_entryCreatedDate='2017/7/28 13:02:00';loadViewCount(cb_entryId);</script>

原创粉丝点击