es6(ES2015)總結

es各個版本的兼容性   http://kangax.github.io/compat-table

             es6(ES2015)在IE10+、chorme、firefox、移動端和NodeJs都能得到有效支持。

對於不支持es6的情況,有兩種方式處理:

(1)在線轉換 

//使用babel  babel也叫browser.js  注意指定script的type="text/bable"
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>es6在線轉換</title>
    <script src="browser.js" charset="utf-8"></script>
    <script type="text/babel">
        let a=1;
        let b=2;
        alert(a+b);
    </script>
</head>
<body>
    
</body>
</html>

(2)提前編譯【推薦】

//安裝babel  在這之前你應該安裝好node.js,因爲npm是隨同NodeJS一起安裝的包管理工具
npm i babel-cli -g
//使用babel命令進行編譯  在這之前你也需要對babel進行配置
babel es6.js -o compiled.js

1、let聲明

es5變量聲明方式var存在兩個問題:①變量提升,即變量不需要先聲明後使用,亦可先使用後聲明。②變量的作用域只有兩種:全局作用域和局部作用域。

let聲明的變量作用域爲塊級作用域,且必須先聲明後使用,使代碼更加嚴謹。

看下面這題,輸出結果應爲多少?

var a = 10;
(function(){
    console.log(a);
    var a = 100;
})();

答案是undefined,因爲var聲明變量的提升效果,這裏相當於:

var a = 10;
(function(){
    var a;
    console.log(a);
    a = 100;
})();

另外,值得注意的是,JavaScript永遠是先解析聲明函數,再解析變量。

var a = 1;
function a(x){
  return 2*x;
}
console.log(a);  //1

 

此時,還有一種情況需要注意:

 

var a;
function a(x){
  return 2*x;
}
console.log(a);  //function a

這裏是由於a沒有被賦值,還是指向回原來的function a();

下面列出一個在學習中仍未解決的問題:

var a=1;
function foo(){
    if(false){
        var a=2;
    }
    console.log(a);
}
foo();
//執行結果:undefined

 

2、const聲明

 

定義後必須賦值,且賦值後不可改變。

①賦常量

②賦變量

③賦數組

④賦對象

由上面的結果可知,對const賦予常量和變量不能改變其值。但是對const賦予數組和對象,只需要更改數組或對象的值,const裏的值也發生了改變,說明對於const對於數組和對象不變的是引用。

注意:let / const不能重複聲明 ,var在非嚴格模式下能夠重複聲明

3、箭頭函數(作爲了解函數的一種新的寫法)

function show(){
    /*es5函數寫法*/
}

let show = ()=>{
    /*箭頭函數寫法*/
}

(1)如果只有一個參數,()可以省略

(2)如果只有一個return,{}可以省略 

function show(a){
   return a*2;   //es5寫法
}

//es6箭頭函數()和{}省略,這裏的參數和return個數必須只能是一個,多也不行少也不行
let show = a => a*2;

4、變量的解構賦值(數組法)

var [a,b,c]=[1,2,3];
//相當於 var a=1,b=2,c=3;
var [a,[b,c]]=[1,[2,3]];
//相當於 var a=1,b=2,c=3;
var [a,b='default',c='default']=[1,2];
//a=1,b=2,c='default'
var [a,b,c]=[1,2];
//a=1,b=2,c=undefined
var [a,...c]=[1,2,3];
//a=1,c=[2,3]

5、變量的解構賦值(對象法)

var obj = {a:1,b:2};
var {a,b}=obj;  //相當於var a=1,b=2;
var obj = {a:1,b:2};
var {a:A,b}=obj;
//a被替換成A,相當於var A=1,b=2;
//亦可設置默認值
 var obj = {a:1};
 var {a:A=3,b=4}=obj; //A=1,b=4
var a,b;
var obj = {a:1,b:2};
({a,b}=obj);
//注意這裏要加上括號,因爲若不加上括號,js解析器會認爲“{”後面是代碼塊

複雜點的解構賦值:

var obj = {
   arr:['Yo',{a:1}]
}
var {arr:[greet,{a}]}=obj;
//greet='Yo',a=1
//結構對上就可以了

注意:(1)左右兩邊結構相同纔能有效賦值(2)聲明賦值不能分開

let [a,b,c];
[a,b,c] = [12,5,8];
//這種寫法會報錯  
//Uncaught SyntaxError: Missing initializer in destructuring declaration

6、解構賦值的一些其他用法(字符串,傳參)

①讀取字符串長度

let {length}="hello"; //變量length=5  {}裏面必須是length

②字符串賦值

let [a,b,c]="ion";
//a='i', b='o', c='n' 

③函數傳參解構

var arr=[1,2];
function test([a,b]){
   console.log(a+"  "+b);
}
test(arr);  //1 2
var obj={b:2};
function test({b,a=10}){
   console.log(a+"  "+b);
}
test(obj);  //10 2

 

7、新增字符串方法

includes()        startsWith()     endsWith()     repeat()

console.log('You'.indexOf('Y') !== -1);//原來判斷字符串是否包含Y的方法 true
console.log('You'.includes('Y'));  
//es6判斷字符串是否包含Y  true
console.log('You'.startsWith('Y'));//是否以Y開始  true
console.log('You'.endsWith('u'));//是否以u開始   true
console.log('You'.repeat('3'));//重複字符3次   YouYouYou

8、模板字符串

let title='hello world!';
let tpl1='<div>'+'<span>'+title+'</span>'+'</div>';
let tpl2=`
    <div>
        <span>${title}</span>
    </div>
 `;
    console.log("tpl1",tpl1);
    console.log("tpl2",tpl2);

打印結果如下:

es6${}裏面還能內嵌反斜號添加其他變量,如下:

let tpl2=`
    <div>
        <span>${title + `<span>${1234}</span>`}</span>
    </div>
`;

9、數組(這裏的函數可以看成對數組每一項進行循環的操作)

map            映射                         一 一對應              如把分數數組映射成及格情況數組     

let score = [12,53,89,65,49,99,56];
//注意下面用了箭頭函數的寫法  注意參數只能有一個,這裏我們命名爲item
//每次return把結果傳給接收變量
let result = score.map(item => item>=60?"及格":"不及格"); 
console.log(result);  
//["不及格", "不及格", "及格", "及格", "不及格", "及格", "不及格"]

reduce        彙總          一堆出來一個         如求和、算平均數       

let array = [12,53,89,65,49,99,56];
//第一個參數temp是上次循環返回值
//第二個參數item是數組的當前項,第一次是12,第二次是53 。。。。。
//第三個參數是指針,從1開始
//每次return把結果傳入下次形參,直到遍歷到最後一個數
let result = array.reduce(function(temp,item,index){
    return temp+item;
});
alert(result);

filter            過濾器         只顯示符合條件的值

let score = [12,53,89,65,49,99,56];
//item爲數組的當前項,返回true則顯示,false則不顯示,最後返回顯示的數組
let result = score.filter(function(item){
    if(item<60){
       return false;
    }else{
       return true;
    }
});
alert(result);  //89,65,99


//------------------上面的代碼可用箭頭函數簡寫爲-----------------
let score = [12,53,89,65,49,99,56];
let result = score.filter(item=>item>=60);
alert(result);   //89,65,99

forEeach    循環(迭代)   

let array = [12,53,89,65,49,99,56];
//第一個參數是數組當前項,第二個參數是索引
array.forEach((item,index)=>{
   alert(index+","+item);
});

9、Symbol數據類型

ES5 的對象屬性名都是字符串,這容易造成屬性名的衝突。比如,你使用了一個他人提供的對象,但又想爲這個對象添加新的方法(mixin 模式),新方法的名字就有可能與現有方法產生衝突。如果有一種機制,保證每個屬性的名字都是獨一無二的就好了,這樣就從根本上防止屬性名的衝突。這就是 ES6 引入Symbol的原因。

 

對變量或值調用 typeof 運算符將返回下列值之一:

  • undefined - 如果變量是 Undefined 類型的
  • boolean - 如果變量是 Boolean 類型的
  • number - 如果變量是 Number 類型的
  • string - 如果變量是 String 類型的
  • object - 如果變量是一個對象或 Null或者數組 
  • function -如果變量是個函數名
  • symbol  -es6引入的數據類型

注意不要和JavaScript基本數據類型搞混,基本數據類型有7個:undefined、null、Boolean、String、Number、Object、Symbol     (根據阮一峯老師的教程,基本數據類型就這7種,不包括Array)

①每次創建Symbol,它的值都不一樣

let a = Symbol();
let b = Symbol();
console.log(a === b);   //false

②Symbol裏面可以傳入一個參數,用於描述你創建的Symbol,傳入參數對他的值沒有影響

let a=Symbol('this is a Symbol');

③應用:在不同的塊中,臨時重寫變量

let name =Symbol();
{
    var person = {};
    person[name] ='file1';
    console.log('person[name]',person[name]);  //file1
}
{
    let name = Symbol();
    person[name] = 'file2';
    console.log('person[name]',person[name]);  //file2
}
console.log('person[name]',person[name]); //file1

④Symbol 值不能與其他類型的值進行運算,會報錯。

let sym = Symbol('My symbol');
"your symbol is " + sym        // TypeError: can't convert symbol to string
`your symbol is ${sym}`        // TypeError: can't convert symbol to string

⑤Symbol 值作爲對象屬性名時,不能用點運算符

const mySymbol = Symbol();
const a = {};

a.mySymbol = 'Hello!';
a[mySymbol] // undefined
a['mySymbol'] // "Hello!"

10、Proxy

var user = new Proxy({},{
    get:function(obj,prop){
         if(prop == 'full_name')
            return obj.fname + ' ' +obj.lname;
}})

user.fname='Bob';
user.lname = 'Wood';
console.log("user.full_name: ",user.full_name);  //user.full_name:Bob Wood
console.log("user.age: ",user.age);  //undefined


11、Set

Set裏面數組值唯一,不重複

var s = new Set([1,2,3,3]);
console.log('s.size', s.size);     //3
console.log('s', s);              // {1,2,3}

s.add(4);              //添加4
console.log('s', s);   //{1,2,3,4}

s.delete(2);           //刪除2
console.log('s', s);   //{1,3,4}

console.log('s.has(5)',s.has(5));   //false   判斷Set是否包含5


s.clear();           //清空Set
console.log('s', s)   //{}

12、面向對象

es6之前寫法:

//爲了區分函數和類,在es5中類首字母大寫   User是這裏是構造函數
function User(name,pass){
    this.name = name;
    this.pass = pass;
}

User.prototype.showName = function(){
    alert(this.name);
}

User.prototype.showPass = function(){
    alert(this.pass);
}

var u1 = new User('ion','123456');
u1.showName();
u1.showPass();

es6寫法:

//這裏的constructor就相當於構造器,定義方法不需要指定function,函數之間不需要符號(如逗號)分隔
class User{
     constructor(name,pass){
          this.name = name;
          this.pass = pass;
      }

      showName(){
          alert(this.name);
      }

      showPass(){
          alert(this.pass);
      }
}

var u1 = new User('ion','123456');
u1.showName();
u1.showPass();

13、繼承

es6之前寫法:

function User(name,pass){
    this.name = name;
    this.pass = pass;
}
User.prototype.showName = functi
    alert(this.name);
}
User.prototype.showPass = functi
    alert(this.pass);
}
function VipUser(name,pass,level
    User.call(this,name,pass);
    this.level = level;
}
VipUser.prototype = new User();
VipUser.prototype.constructor = 
VipUser.prototype.showLevel = fu
    alert(this.level);
}
var u2 = new VipUser('ion','1234
u2.showName();
u2.showPass();
u2.showLevel();

es6寫法:

class User{
    constructor(name,pass){
        this.name = name;
        this.pass = pass;
    }
    showName(){
        alert(this.name);
    }
    showPass(){
        alert(this.pass);
    }
}

//extends 指定繼承自who  這裏的extends和super(超類)與Java比較類似
class VipUser extends User{
    constructor(name,pass,level){
        //繼承父類的構造函數與方法
        super(name,pass);  
        this.level = level;
    }
    showLevel(){
        alert(this.level);
    }
}
var u1 = new VipUser('ion','123456',3);
u1.showName();
u1.showPass();
u1.showLevel();

14、JSON

json對象與json字符串互換:

//json對象轉字符串方法      JSON.stringify();
//json字符串轉json對象方法  JSON.parse();
let json = {a:5,b:4};
let str_json = JSON.stringify(json);
let obj_json = JSON.parse(str_json);

console.log(str_json);          //輸出爲{"a":5,"b":4},即str_json = '{"a":5,"b":4}';
console.log(typeof(str_json));  //string

console.log(obj_json);          //{a:5,b:4}
console.log(typeof(obj_json));  //object

注意:js字符串要解析成json對象要符合一定的標準。

(1){}裏面只能用雙引號

(2)key必須使用雙引號包裹

let tjson = '{"a":"abc","b":2,"c":3}';   正確
let fjson1 = '{a:"abc",b:2,c:3}';   錯誤,key沒有用雙引號包裹
let fjson2 = "{'a':'abc','b':2,'c':3}";  錯誤,json字符串裏面只能用雙引號

另外,es6中,json的key和value一樣的時候,可以省略只寫一個。json裏面的方法可以直接去掉冒號和function

let a=12;
//es6之前寫法
let json = {
    a    : a,
    show : function(){
        alert(this.a);
    }
}
//es6寫法
let newJson = {
    a,
    show(){
        alert(this.a);
    }
}

15、Promise

在JavaScript的世界中,所有代碼都是單線程執行的。由於這個“缺陷”,導致JavaScript的所有網絡操作,瀏覽器事件,都必須是異步執行。異步執行可以用回調函數實現:

<script src="jquery.js"></script>
<script>
    $.ajax({
        url      : "data/userInf.txt",
        dataType : "json",
        type     : "POST",
        async    : true,
        success  : function(data){
                       //do something
                   },
        error    : function(erroThrow){
                       console.log(erroThrow);
                   }
    });
</script>

這種把回調函數寫在ajax的操作不僅不太好看,同時也不便於代碼的複用。

古人云:“君子一諾千金”,這種“承諾將來會執行”的對象在JavaScript中稱爲Promise對象。Promise對象的主要作用就是消除異步操作,用同步一樣的方式來說書寫異步代碼。

let p = new Promise(function(resolve,reject){
    //這裏的resolve和reject都是函數
    //resolve  成功了
    //reject   失敗了
    $.ajax({
        url      : "data.txt",
        dataType : "json",
        success  : function(data){
            resolve(data);
        },
        error    : function(errorThrow){
            reject(errorThrow);
        }
    });
});

/*then()的第一個函數就相當於resolve,第二個函數就相當於reject。參數與上面的resolve和reject內的參數一致*/
p.then(function(data){
    alert("成功了"+data);
},function(errorThrow){
    alert("失敗了");
    console.log(errorThrow);
});

//ajax操作不能用file開頭的地址打開,需要使用localhost,即在服務器上運行代碼,否則會出現跨域問題

上面的Promise對象就成功的把回調函數與異步邏輯給區分了開來。

Promise有兩個方法all()和race(),分別用於並行的ajax操作和容錯式的ajax操作。

let p1 = new Promise(function(resolve,reject){
    $.ajax({
        url      : "data.txt",
        dataType : "json",
        success  : function(data){
            resolve(data);
        },
        error    : function(errorThrow){
            reject(errorThrow);
        }
    });
});
let p2 = new Promise(function(resolve,reject){
    $.ajax({
        url      : "data2.txt",
        dataType : "json",
        success  : function(data){
            resolve(data);
        },
        error    : function(errorThrow){
            reject(errorThrow);
        }
    });
});

//all()方法必須所有的異步請求成功纔會執行resolve
//注意all()裏面的參數是Promise對象數組,then()的第一個和第二個函數參數是resolve函數和reject函數的參數數組
Promise.all([p1,p2]).then(function(array){
    let [res1,res2] = array;
    alert("全都成功了");
    console.log(res1);
    console.log(res2);
},function(){
    alert("至少一個失敗了");
});

當然,對於上面這種all()方法的情況,把創建Promise對象的操作封裝成一個函數會顯得代碼簡潔很多,這裏這樣寫感覺會比較好理解。封裝成函數的代碼如下:

function createPromise(url){
    return new Promise(function(resolve,reject){
        $.ajax({
            url      : url,
            dataType : "json",
            success  : function(data){
                resolve(data);
            },
            error    : function(errorThrow){
                reject(errorThrow);
            }
        });
    });
}
Promise.all([
    createPromise("data.txt"),
    createPromise("data2.txt")
]).then(function(array){
    let [res1,res2] = array;
    alert("全都成功了");
    console.log(res1);
    console.log(res2);
},function(){
    alert("至少一個失敗了");
});

Promise.race()方法用法如下:

function createPromise(url){
    return new Promise(function(resolve,reject){
        $.ajax({
            url      : url,
            dataType : "json",
            success  : function(data){
                resolve(data);
            },
            error    : function(errorThrow){
                reject(errorThrow);
            }
        });
    });
}
/*有些時候,多個異步任務是爲了容錯。比如,同時向兩個URL讀取用戶的個人信息,只需要獲得先返回的結果即可。其
餘結果拋棄*/
Promise.race([
    createPromise("data.txt"),
    createPromise("data2.txt")
]).then(function(array){
    let res1 = array;
    alert("至少一個成功了");
    console.log(res1);
},function(){
    alert("全部失敗了");

在jquery的較新版本中也有對Promise對象的封裝,使用jquery3.2以上的版本,則可以使寫Promise對象的代碼更加簡潔。

//jquery3.2以上版本$.ajax方法返回值就是一個Promise對象
Promise.race([
    $.ajax({url:'data.txt',dataType:'json'}),
    $.ajax({url:'data2.txt',dataType:'json'}),
]).then(function(array){
    let res1 = array;
    alert("至少一個成功了");
    console.log(res1);
},function(){
    alert("全部失敗了");

16、generator函數(生成器函數)

最大特點:中間可以通過yield暫停

//這裏的“*”代表這是一個generator函數,*號可以靠function放,可以靠show放,也可以放在兩者中間各帶空格
//就是不可以這樣:function*show(){}
function *show(){
    alert("a");
    yield;
    alert("b");
    yield;
    alert("c");
}
//generator函數是踹一腳走一步,和普通函數一條路走到底不同
//generator函數不能直接執行,利用其返回的generator對象的next()方法控制走到哪一步
let genObj = show();
genObj.next();   //alert("a")
genObj.next();   //alert("b")
genObj.next();   //alert("c")

(1)通過next()給yield傳值

function *show(a){
    alert("a"+a);  //a1
    let b = yield;
    alert("b"+b);  //b3
    let c = yield;
    alert("c"+c);  //b4
}

//開始沒有yield,可以通過函數show傳參來傳值
let genObj = show(1);
//如果沒有第一個next(),什麼都不會輸出.
genObj.next(2);    
/*從輸出可以看出,給第一個next()傳參是沒有意義的,在執行時可以猜測這一步是進入函數的意思,並沒有遇到yield來傳值*/
genObj.next(3);
genObj.next(4);

(2)yield給next()傳值

function *show(){
    alert("a");
    yield 1;

    alert("b");
    yield 2;

    alert("c");
    //最後沒有yield,可以通過return返回值給next()
    return 3;
}

let genObj = show();
let res1 = genObj.next();
let res2 = genObj.next();
let res3 = genObj.next();
console.log(res1);  //{done:false,value:1}
console.log(res2);  //{done:false,value:2}
console.log(res3);  //{done:true,value:3}

//done即指是否執行到最後一步

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章