es6重要內容用法

ES6

1、ECMA歷史

組成部分: ECMA、DOM、BOMjavascript

  1. 什麼是ECMA?全稱 ECMAScript 簡寫 ECMA 或 EShtml

    ECMA是一個標準,JS是實現java

    例如: HTML5 是標準,chrome,FF,IE10是實現node

    未來也可能有 xxxscript 實現ECMAgit

  2. 目前的版本:es6

    1. 低級瀏覽器: 主要支持es3.1,3.2
    2. 高級瀏覽器: 正從ES5過分到ES6
  3. 版本進化過程github

    1996            ES1.0       js穩定    Netscape將js提交給ECMA組織
    1998            ES2.0       正式發佈
    1999            ES3.0       瀏覽器普遍支持
    2007            ES4.0       ES4過於激進,被廢除
    2008            ES3.1       4.0變爲縮水版的3.1  代號:Harmony
    2009            ES5.0       ES5 正式發佈,同時公佈了javascript.next-6.0前身
    2011            ES5.1       成爲ISO國際標準
    2013.3          ES6.0       ES6.0制定草案
    2013.12         ES6.0       發佈草案
    2015.6          ES6.0       ES6.0預計發佈,同時發佈 es7.0正在制定草案
    
  4. 兼容性:ajax

    目前爲止ES5 ES6支持狀況還湊合
    
    nodejs用的就是chrome內核,在node中已經可使用es6的不少特性了
    
    ES5和ES6已經逐漸淪爲後臺語言
    

    1. 在瀏覽器中如何使用?須要編譯工具,把ES6語法編譯成ES5
        babel
        traceur     ---google出的編譯器
        bootstrap   引導程序
        <script src="traceur.js"></script>
        <script src="bootstrap.js"></script>
        <script type="module">
            let a = 12;
        </script>


        <script src="https://traceur-compiler.googlecode.com/git/bin/traceur.js"
                type="text/javascript"></script>
        <script src="https://traceur-compiler.googlecode.com/git/src/bootstrap.js"
                type="text/javascript"></script>
        <script>
          traceur.options.experimental = true;
        </script>
        <script type="module" src="js/calc.js"></script>

    2. 在線編譯:主要用於測試

        a. babeljs.io/repl
        b. google.github.io/traceur-compiler/demo/repl.html

    3. 在node中能夠直接使用

        "use strict"
        let a = 12;
        console.log(a);

        a. 直接用,須要添加 use strict
        b. node --harmony_destructuring xx.js

2、定義變量 let和const

  1. ES6新增了let命令,用來聲明變量。它的用法相似於var,可是所聲明的變量,只在let命令所在的代碼塊內有效。

let定義的變量不能在相同做用域下,重複聲明同一個變量chrome

    function () {
        let a = 10;
        var a = 1;
    }

    function () {
        let a = 10;
        let a = 1;
    }

如下現象用來理解塊級做用域bootstrap

現象1:

    {
        let a = 10;
        var b = 1;
    }
    console.log(a);
    console.log(b);

結論:let聲明的變量盡在 {}內有效

現象2: let聲明的變量僅在當前做用域中有效

    for(let i=0;i<10;i++){}
    console.log(i);

現象3:

    var a = [];
    for (var i = 0; i < 10; i++) {
        a[i] = function () {
            console.log(i);
        };
    }
    a[6]();
    //========
    var a = [];
    for (let i = 0; i < 10; i++) {
        a[i] = function () {
            console.log(i);
        };
    }
    a[6]();
    i是let聲明的,因此當前的 i僅在本輪循環有效,直接會被解析成數字。

現象4:循環語句是父做用域,循環體是一個獨立的做用域,互不影響。

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

現象5: 不存在變量提高

    // var 的狀況
    console.log(foo);
    var foo = 2;

    // let 的狀況
    console.log(bar);
    let bar = 2;

現象6: 暫時性死區

    var tmp = 123;

    if (true) {
        tmp = 'abc'; // ReferenceError
        let tmp;
    }

報錯:由於當使用let時,當前快做用域被封閉,let定義的變量僅可以在以後使用

爲何須要塊級做用域?

  1. 內層變量可能會覆蓋外層變量。

    var tmp = new Date();
    
    function f() {
        console.log(tmp);
        if (false) {
            var tmp = 'hello world';
        }
    }
    f();
    
  2. 用來計數的循環變量泄露爲全局變量。

    var s = 'hello';
    for (var i = 0; i < s.length; i++) {
        console.log(s[i]);
    }
    console.log(i); // 5
    

塊級做用域試題

1.

    function f1() {
        let n = 5;
        if (true) {
            let n = 10;
        }
        console.log(n); // 5
    }
  1. 自執行函數封閉做用域,能夠用塊做用域替代

    // IIFE 寫法
    (function () {
        var tmp = ...;
        ...
    }());
    
    // 塊級做用域寫法
    {
        let tmp = ...;
        ...
    }
    

3.

    function f() { console.log('I am outside!'); }

    (function () {
          if (false) {
            // 重複聲明一次函數f
            function f() { console.log('I am inside!'); }
          }

          f();
    }());

2、const 聲明一個只讀的常量。一旦聲明,常量的值就不能改變

const聲明的變量不得改變值,這意味着,const一旦聲明變量,就必須當即初始化,不能留到之後賦值。

  1. const的做用域與let命令相同:只在聲明所在的塊級做用域內有效。

    if (true) {
        const MAX = 5;
    }
    MAX
    

3、解構賦值

  1. 什麼是解構賦值? 左邊一種結構,右邊一種結構,左右一一對應進行賦值

  2. 分類

  3. 數組解構賦值 **

  4. 對象解構賦值 **

  5. 字符串解構賦值

  6. 布爾值解構賦值

  7. 函數參數解構賦值

  8. 數值解構賦值

1 解構賦值基本方式

    let [x,y] = [1,2];
    console.log(x,y);//1,2

2 ...解構賦值

    {
        let a,b,rest;
        [a,b,...rest] = [1,2,3,4,5,6];
        console.log(a,b,rest);//rest [3,4,5,6]
    }

3 對象解構賦值

    //對象的解構賦值
    {
        let a,b;
        ({a,b} = {a:1,b:2});
        console.log(a,b);
    }

4 默認值(沒有找到配對有默認值使用默認值,沒有默認值值爲 undefined)

    // 解構賦值的默認值
    {
        let a,b,c,rest;
        [a,b,c=3,d] = [1,2];
        console.log(a,b,c,d);
    }

5 變量交換

    //利用解構賦值交換變量中的值
    {
        let a = 1;
        let b = 2;
        [a,b] = [b,a];
        console.log(a,b);
    }

6 函數返回多個值

    function f(){
        return [1,2];
    }
    let [a,b] = f();
    console.log(a,b);

7 選擇性的接收 返回值

    {
        function f(){
            return [5,6,7,8,9];
        }
        let [a,,,,b] = f();
        console.log(a,b);
    }

8 我只關心第一個,其餘的先放數組裏

    {
        function f(){
            return [5,6,7,8,9];
        }
        let [a,...b] = f();
        console.log(a,b);
    }

9 對象結構賦值

    {
        let o = {name:'yuonly',age:20};
        let {age,name} = o;
        console.log(name,age);
    }

10 能夠替代 arguments

    // ... 能夠替代arguments
    {
      function test3(...arg){
        for(let v of arg){
          console.log('rest',v);
        }
      }
      test3(1,2,3,4,'a');
    }

4、對象擴展

1. 簡潔表示法

    //簡潔表達
    {
        let a = 1;
        let b = 2;
        //ES5
        let es5 = {
            a:a,
            b:b
        }
        console.log(es5);
        //ES6
        let es6 = {
            a,
            b
        }
        console.log(es6);

    }
    {
        //若是有方法的處理方式
        // ES5
        let es5 = {
            hello:function(){
                console.log('hellow');
            }
        }
        //ES6
        let es6 = {
            hello(){
                console.log('hello');
            }
        }
    }

2. 屬性表達式

    let a = 'b';
    let es5_obj = {//es5中對象的 key必須是固定的
        a:'c'
    }
    //es6
    let es6_obj = {//屬性值能夠是變量
        [a] : 'c'
    }
    console.log(es6_obj,'es6_obj');

3. 擴展運算符(ES7語法,支持很差,瞭解)

    {
        //babel不支持,沒法編譯
        let {a,b,...c} = {a:'test',b:'kill',c:'ddd',d:'ccc'}
        c = {
            c:'ddd',
            d:'ccc'
        }
    }

4. object新增API

    {
        // is :判斷兩個值是否相等
        console.log('字符串',Object.is('abc','abc'));
        console.log('數組',Object.is([],[]));//兩個不一樣的地址

        //assign : 潛拷貝
        console.log('拷貝',Object.assign({a:'a'},{b:'b'}));

        // entries
        let test = [k:123,o:456];
        for(let [key,value] of Object.entries(test)){
            console.log([key,value]);
        }
    }

5、類

1 基本語法

    {
        //基本定義和生成實例
        class Person{
            constructor(name='laozhou'){
                this.name = name;
            }
        }
        let p1 = new Person('小王');
        console.log('構造函數和實例',p1);
    }

2 類的繼承

    {
        //繼承
        class Father{
            constructor(name='laozhou'){
                this.name = name;
            }
        }
        class Child extends Father{

        }
        console.log('子類的實例',new Child());
        console.log('子類本身傳',new Child('小劉'))

    }


    {
        //子類如何覆蓋父類的值
        class Father{
            constructor(name='laozhou'){
                this.name = name;
            }
        }
        class Child extends Father{
            constructor(name='child'){
                //this.type = 'boy';//super必須在第一行,不然報錯
                super(name);//調用父親類的構造函數
                this.type = 'boy';
            }
        }
        console.log('子類覆蓋父類屬性的實例',new Child());
    }

3 靜態屬性

    //靜態屬性
    {
        class Person{
            constructor(name='laozhou'){
                this.name = name;
            }
        }
        //靜態屬性的定義,是直接給類下的屬性賦值,該屬性就是靜態屬性
        Person.type = 'text';//type就是靜態屬性
    }

4 靜態方法

    //靜態方法
    {
        class Person{
            constructor(name='laozhou'){
                this.name = name;
            }
            static tell(){//至關於原型下的方法,是屬於類自己的,用類來調用
                console.log('tell');
            }
        }
        Person.tell();
    }

5 getter-setter

    {
        //getter   setter
        class Father{
            constructor(name='laozhou'){
                this.name = name;
            }
            //此處longName不是函數而是屬性,至關於新增了一個屬性 longName
            get longName(){
                return 'yu_'+this.name;
            }
            set longName(value){
                this.name = value;
            }
        }

        let f1 = new Father();
        console.log('getter',f1.longName);
        f1.longName = 'hello';
        console.log('setter',f1.longName);
    }

6、promise

promise是異步變成的解決方案(解決回調地獄)

1 基本寫法

    {
        //es5 中的異步操做
        let ajax = function(callback){
            console.log('執行');
            setTimeout(function(){
                callback && callback.call();
            },1000);
        }
        ajax(function(){
            console.log('timeout1');
        })
    }

    {
        //ES6
        let ajax = function(){
            console.log('執行2');
            return new Promise(function(resolve,reject){
                setTimeout(function(){
                    resolve();//resolve後會有then方法,執行後續操做
                },1000);
            })
        }
        ajax().then(function(){
            console.log('promise','timeout');
        })
    }

2 promise.all 全部的 異步操做都成功後,在去執行一個動做。例子,圖片都加在完成以後再顯示到頁面

    //promise.all :把多個promise實例當作一個promise實例,當全部的狀態都完成以後,纔會觸發新的promise對象的then方法

    //應用,好比廣告中有三張圖,須要三張圖都加載再去更新dom
    {
        //全部圖片加載完成在加載頁面
        function loadImg(src){
            return new Promise((resolve,reject)=>{
                let img = document.createElement('img');
                img.src = src;
                img.onload = function(){
                    resolve(img);
                }
                img.onerror = function(){
                    reject(err);
                }
            })
        }

        function showImg(imgs){
            imgs.forEach(function(img){
                document.body.appendChild(img);
            })
        }

        Promise.all([
            loadImg('https://img10.360buyimg.com/n4/s260x260_jfs/t3079/363/6070979658/42126/5b5c2f39/589af086N4a3bed39.jpg'),
            loadImg('https://img14.360buyimg.com/n4/s260x260_jfs/t4345/284/2534342556/119746/550dee37/58d34a9dNf0bd717f.jpg'),
            loadImg('https://img13.360buyimg.com/n4/s260x260_jfs/t3259/170/5587914266/144572/64259fc5/5873347aN14e34822.jpg'),
        ]).then(showImg);

    }

3 promise.race 誰先到加載誰

    {
        //promise.race  誰先回來處理誰,先到先得
        function loadImg(src){
            return new Promise((resolve,reject)=>{
                let img = document.createElement('img');
                img.src = src;
                img.onload = function(){
                    resolve(img);
                }
                img.onerror = function(){
                    reject(err);
                }
            })
        }

        function showImgs(img){
            let p = document.createElement('p');
            p.appendChild(img);
            document.body.appendChild(p);
        }

        Promise.race([
            loadImg('https://img10.360buyimg.com/imgzone/jfs/t5149/215/1247256617/226900/c371168/590dcc2bN2234f761.jpg'),
            loadImg('https://img14.360buyimg.com/n4/s260x260_jfs/t4345/284/2534342556/119746/550dee37/58d34a9dNf0bd717f.jpg'),
            loadImg('https://img13.360buyimg.com/n4/s260x260_jfs/t3259/170/5587914266/144572/64259fc5/5873347aN14e34822.jpg'),
        ]).then(showImgs);
    }

4 promise可讓代碼執行的步驟更清晰,過程更可控

    //使用promise後,更清晰
    {
        let oBox = document.getElementById('box');

        function toWidth(w){
            return new Promise(function(resolve,reject){
                let timer = setInterval(function(){
                    var oldWidth = oBox.clientWidth;
                    if(oldWidth>w){
                        clearInterval(timer);
                        resolve();
                    }
                    oBox.style.width = oldWidth + 10 + 'px';
                },100);
            })
        }

        function toHeight(h){
            return new Promise(function(resolve,reject){
                let timer = setInterval(function(){
                    var oldHeight = oBox.clientHeight;
                    if(oldHeight>h){
                        clearInterval(timer);
                        resolve();
                    }
                    oBox.style.height = oldHeight + 10 + 'px';
                },100);
            })
        }

        function toSmall(size){
            return new Promise(function(resolve,reject){
                let timer = setInterval(function(){
                    var oldWidth = oBox.clientWidth;
                    var oldHeight = oBox.clientHeight;
                    if(oldWidth<size || oldHeight<size){
                        clearInterval(timer);
                        resolve();
                    }
                    console.log(123);
                    oBox.style.width = oldWidth - 10 + 'px';
                    oBox.style.height = oldHeight - 10 + 'px';
                },100);
            })
        }

        //使用promise後,更清晰,能夠隨意更改流程。
        toHeight(400)
            .then(function(){
                return toWidth(600);
            })
            .then(function(){
                return toHeight(300);
            })
            .then(function(){
                return toSmall(100);
            })
            .then(function(){
                return toHeight(400);
            })
    }

    //ES5
    {
        function toWidth(w,callback){
            let timer = setInterval(function(){
                var oldWidth = oBox.clientWidth;
                if(oldWidth>w){
                    clearInterval(timer);
                    callback && callback();
                }
                oBox.style.width = oldWidth + 10 + 'px';
            },100);
        }

        function toHeight(h,callback){
            let timer = setInterval(function(){
                var oldHeight = oBox.clientHeight;
                if(oldHeight>h){
                    clearInterval(timer);
                    callback && callback();
                }
                oBox.style.height = oldHeight + 10 + 'px';
            },100);
        }

        function toSmall(size,callback){
            let timer = setInterval(function(){
                var oldHeight = oBox.clientHeight;
                var oldWidth = oBox.clientWidth;
                if(oldHeight<size){
                    clearInterval(timer);
                    callback && callback();
                }
                oBox.style.width = oldWidth - 10 + 'px';
                oBox.style.height = oldHeight - 10 + 'px';
            },100);
        }

        //代碼可讀性差,並且很難控制執行順序
        toWidth(500,function(){
            toHeight(300,function(){
                toSmall(100,function(){
                    toWidth(400,function(){
                        toHeight(100,function(){

                        })
                    })
                });
            })
        });
    }

7、模塊化

1. 基本概念:每個文件都是獨立的做用域,一個模塊,都是獨立存在,不會互相影響

2. ES6模塊化語法

方式一: 優勢:能夠只導出部分模塊。弊端,導出模塊特別多的時候,不能一眼看出都導出了那些模塊
    //模塊的導出 module1.js
    export let a = 123;
    export function test(){
        console.log('test');
    }
    export class Hello{
        test(){
            console.log('class');
        }
    }
    //模塊的導入 entry.js
    a as A 起別名 A,外部使用A來操做a
    import {a as A,test,Hello} from './lesson/6.module/module1.js';

    console.log(A,test,Hello);

    //導入全部模塊放入 obj對象下
    import * as obj from './lesson/6.module/module1.js';
    console.log(obj.a);
方式二:推薦方式
    //導出 module2.js
    let num = 123;
    let test = function(){
        console.log('test');
    }
    class Person{
        test(){
            console.log('Person');
        }
    }
    //1,批量導出,一目瞭然導出了那些東西給外部 2, 沒有起名字,將命名權給倒入方。
    export default {
        num,
        test,
        Person
    }


    //導入  entry.js
    import M from './lesson/6.module/module2.js';
    console.log(M,M.num);
    M.test()

8、函數擴展(箭頭函數)

  • 參數默認值
  • rest參數
  • 擴展運算符(rest參數的逆運用)
  • 箭頭函數
  • 尾調用

1 參數默認值

    {
        function test(x,y=10){
            console.log('默認值',x,y);
        }
        test(1);
        test(99,88);
    }
    // 有默認值的參數後面,不能有 沒有默認值的參數
    {
        function test(x,y=10,c){//會報錯,在默認值後面不能有 沒有默認值的參數
            console.log('默認值',x,y);
        }
    }
    //函數的做用域
    {
        let x = 'test';
        function test2(x,x=y){
            console.log('做用域——',x,y);
        }
        test2('new');
    }
    //沒有的時候用上面的
    {
        let x = 'test';
        function test2(c,y=x){
            console.log('做用域2',x,y);
        }
        test2('new');
    }

2 rest參數

    {
        //此時的arg至關因而 arguments
        function test3(...arg){
            for(let v of arg){
                console.log('rest:',v);
            }
        }
        test3(1,2,3,4,5);
    }

3 擴展運算符(rest參數的逆運用)

    {
        console.log(...[1,2,3]);
    }

4 箭頭函數

    {
        let arrow = v=>v*10;
        console.log(arrow(3));

        <!-- let arrow2 = (v)=>{return v*50};
        console.log(arrow2(2)); -->
    }
    至關因而
    {
        let arrow = function(v){
            return v*10;
        }
        console.log(arrow(3));
    }

5 尾調用 :函數的最後一句話是函數,就是爲調用

    {
        function tail(x){
            console.log('tail',x);
        }
        function go(x){
            return tail(x);
        }
        go(123);
    }
相關文章
相關標籤/搜索