js的ES6特性

來源:互聯網
上載者:User

標籤:ons   size   gen   添加   字串串連   初學者   window   自動   函數調用   

一。 let和const關鍵字

let出現之前,js所有的範圍都是以函數為單位的,只要在一個function裡聲明的var,

無論是for迴圈等塊裡面聲明的還是在塊外面聲明的,整個function都可以使用這個var,比如:

function foo() {    for (var i=0; i<100; i++) {        //    }    i += 100; // 仍然可以引用變數i}

我個人的理解是js的提升特性,函數會將裡面聲明的所有var都提升到函數開始的地方,所以整個函數內都共用這些var。

let的出現解決了塊級範圍的問題:

function foo() {    var sum = 0;    for (let i=0; i<100; i++) {        sum += i;    }    i += 1; // SyntaxError}

但是要注意的是,let並沒有提升特性,也就是說不允許在聲明之前就使用,而且在某一個塊中聲明的let變數,會屏蔽掉同名的var變數:

var c = ‘test‘;if (true) {  c = ‘new‘; //ReferenceError  let c;  console.log(c);}

const的是”常量let“,也就是說是有塊級範圍的常量值。 

二。 箭頭函數

箭頭函數使用的最重要一點就是this的使用,一不小心就會出錯。

let a = {  foo: 1,  bar: () => console.log(this.foo)};a.bar(); // undefined

  代碼中的this指向調用a的對象,而不是a本身,如果為a外面沒有定義foo的話,this會一直追溯到window對象,所以this.foo就是undefined了。

如果想調用a,只能使用普通函數:

let a = {  foo: 1,  bar: function() { console.log(this.foo); }};a.bar(); // 1

 再來看一個例子:

var obj = {    birth: 1990,    getAge: function () {        var b = this.birth; // 1990        var fn = () => new Date().getFullYear() - this.birth; // this指向obj對象        return fn();    }};obj.getAge(); // 25

 這裡的this指向調用getAge的對象obj,所以this.birth能取到obj中的birth屬性,該寫法等價於:

var obj = {    birth: 1990,    getAge: function () {        var b = this.birth; // 1990        var that = this;        var fn = function () {            return new Date().getFullYear() - that.birth; // this指向window或undefined        };        return fn();    }};obj.getAge(); // 25

這裡必須使用that來捕獲對象,否則在fn中的this並不是指向obj而是指向調用fn的對象。相比之下,該例中的箭頭函數的使用就很清晰簡潔了。

依我看來,並不應該把箭頭函數歸類為函數,而更應該使用lambda演算或lambda運算式這一稱謂,

這一點在java中做的比較好,不知道為什麼在js中很多人喜歡成為箭頭函數,容易引起混淆。 

三。 字串的使用

(1)多行字串

用反引號 ` ... ` 表示:

alert(`多行字串測試`);

(2)模板字串

var name = ‘小明‘;var age = 20;var message = `你好, ${name}, 你今年${age}歲了!`;alert(message);

模板字串在一定程度上簡化了+號的字串串連作用。

四。 for…of…結構

for…in…迴圈有很多問題,但由於曆史遺留問題至今還在使用。 

for...in...遍曆的實際上是對象的屬性名稱。一個Array數組實際上也是一個對象,它的每個元素的索引被視為一個屬性,

所以當使用for…in…來遍曆數組時,會感覺很彆扭,而且當我們手動給Array對象添加了額外的屬性後,for...in迴圈將帶來意想不到的意外效果,比如:

var a = [‘A‘, ‘B‘, ‘C‘];a.name = ‘Hello‘;for (var x in a) {    alert(x); // ‘0‘, ‘1‘, ‘2‘, ‘name‘}

 這對於很多初學者來說很不習慣,for…of…就避免了這個問題,迴圈則完全修複了這些問題,它只迴圈集合本身的元素:

var a = [‘A‘, ‘B‘, ‘C‘];a.name = ‘Hello‘;for (var x of a) {    alert(x); // ‘A‘, ‘B‘, ‘C‘}

這就是為什麼要引入新的for ... of迴圈。 

五。 Map和Set

Map是一種key-value結構,注意要區分和對象的寫法,不同的key和value通過[ ]來劃定而不是逗號,用逗號串連key和value而不是冒號。

var m = new Map([[‘Michael‘, 95], [‘Bob‘, 75], [‘Tracy‘, 85]]);m.get(‘Michael‘); // 95

Set是一組key的集合,不儲存value,注意和數組的區別,Set中值都是唯一的,重複的值被自動過濾,這也是和普通數組最大的區別。

var s = new Set([1, 2, 3, 3, ‘3‘]);s; // Set {1, 2, 3, "3"} 

六。 iterable類型 

遍曆Array可以採用下標迴圈,遍曆MapSet就無法使用下標。

為了統一集合類型,ES6標準引入了新的iterable類型。

ArrayMapSet都屬於iterable類型。具有iterable類型的集合可以通過新的for ... of迴圈來遍曆。

然而,更好的方式是直接使用iterable內建的forEach方法(注意forEach()方法是ES5.1標準引入的,也就是說時在引入iterable類型之前就引入了),

forEach接收一個函數,每次迭代就自動回調該函數,比如以Array為例。

var a = [‘A‘, ‘B‘, ‘C‘];a.forEach(function (element, index, array) {    // element: 指向當前元素的值    // index: 指向當前索引    // array: 指向Array對象本身    alert(element);});

SetArray類似,但Set沒有索引,因此回呼函數的前兩個參數都是元素本身:

var s = new Set([‘A‘, ‘B‘, ‘C‘]);s.forEach(function (element, sameElement, set) {    alert(element);});

Map的回呼函數參數依次為valuekeymap本身:

var m = new Map([[1, ‘x‘], [2, ‘y‘], [3, ‘z‘]]);m.forEach(function (value, key, map) {    alert(value);});

如果對某些參數不感興趣,由於JavaScript的函數調用不要求參數必須一致,因此可以忽略它們。例如,只需要獲得Setelement

var s = new Set([‘A‘, ‘B‘, ‘C‘]);s.forEach(function (element) {    console.log(element);});

七。 generator

(由於generator的概念比較複雜,詳情請參考廖雪峰老師的網站)

 generator由function*定義(注意多出的*號),並且,除了return語句,還可以用yield返回多次。

直接調用一個generator和調用函數不一樣,f()僅僅是建立了一個generator對象,還沒有去執行它。

真正要執行generator對象有兩個方法,一是不斷地調用generator對象的next()方法,第二個方法是直接用for ... of迴圈迭代。

(1)調用next

next()方法會執行generator的代碼,然後,每次遇到yield x;就返回一個對象{value: x, done: true/false},然後“暫停”。

返回的value就是yield的傳回值,done表示這個generator是否已經執行結束了。如果donetrue,則value就是return的傳回值。

當執行到donetrue時,這個generator對象就已經全部執行完畢,不要再繼續調用next()了。下面來看個例子:

要產生一個自增的ID,可以編寫一個next_id()函數,由於函數無法儲存狀態,故需要一個全域變數current_id來儲存數字:

var current_id = 0;function next_id() {    current_id ++;    return current_id;}

為了避免全域變數的汙染,使用generator來儲存運行狀態:

function* next_id () {    var current_id = 1;    while (true)  {       yield current_id;       current_id ++;    }       return current_id; // 可以不寫}

由於這裡的while並沒有跳出的可能,所以永遠也不會執行return,可以一直調用next方法:

g = next_id(); // 只是建立了一個generator對象,還沒有執行g.next(); // 1g.next(); // 2...

再來看一個可以跳出迴圈的例子:

function* fib(max) {    var        t,        a = 0,        b = 1,        n = 1;    while (n < max) {        yield a;        t = a + b;        a = b;        b = t;        n ++;    }    return a;}

該例子是建立斐波那契數列數列,調用情況如下:

var f = fib(5); // 建立generatorf.next(); // {value: 0, done: false}f.next(); // {value: 1, done: false}f.next(); // {value: 1, done: false}f.next(); // {value: 2, done: false}f.next(); // {value: 3, done: true} f.next(); // {value: undefined, done: true}

注意最後一行的value是undefined,由於在上一行已經return了,所以這一行沒有意義。

(2)使用for…of

直接用for ... of迴圈迭代generator對象,這種方式不需要我們自己判斷done

for (var x of fib(5)) {    console.log(x); // 依次輸出0, 1, 1, 2, 3}

js的ES6特性

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.