成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

ECMAScript 6新特性印象之一:新語法

馬忠志 / 2766人閱讀

摘要:下例實(shí)現(xiàn)了一個(gè)數(shù)組的迭代器在中,可迭代數(shù)據(jù)結(jié)構(gòu)比如數(shù)組都必須實(shí)現(xiàn)一個(gè)名為的方法,該方法返回一個(gè)該結(jié)構(gòu)元素的迭代器。原話是還可以傳遞返回值。

前記

按照規(guī)劃,明年年中,ECMAScript 6(ES6)就要正式發(fā)布了。

最近抽空看了Dr. Axel Rauschmayer的幾篇文章和演講PPT,對(duì)新特性有了些了解。

趁沒忘,抓緊記錄下,夾雜自己的感受。

計(jì)劃分三部分:

新語法

面對(duì)對(duì)象和模塊化

標(biāo)準(zhǔn)庫擴(kuò)充

參考了以下文章/PPT:

Use ECMAScript 6 today

Ecmascript 6 Whats next for Javascript

es6 features

ECMAScript 6: arrow functions and method definitions

Callable entities in ECMAScript 6

Iterators and generators in ECMAScript 6

其他文章:

ECMAScript 6新特性印象之二:面對(duì)對(duì)象和模塊化

總體印象

的確是「design by champions」。各種為了代碼書寫效率進(jìn)行的優(yōu)化,借鑒了近年各種「新」語言的優(yōu)秀特性,靈活性大大提升,閱讀難度也提升了……

不過,熟悉Ruby的看了這些會(huì)放心不少吧。

新語法

1.塊級(jí)作用域 關(guān)鍵字let, const

function order(x, y) {
    if (x > y) {
        let tmp = x;
        x = y;
        y = tmp;
    }
    console.log(tmp === x); // 引用錯(cuò)誤:tmp此時(shí)未定義  
    return [x,y];
}

JS終于有了塊級(jí)作用域變量。雖然在代碼結(jié)構(gòu)層面沒有太大的作用(以前沒有時(shí)也活得很好么,雖然不怎么舒服),但會(huì)讓代碼更加準(zhǔn)確,更易于閱讀。

今年夏天發(fā)布的Swift中也增加了let關(guān)鍵字,雖然有些許區(qū)別,但目的應(yīng)該是差不多——提升代碼可讀性。

2.對(duì)象字面量的屬性賦值簡(jiǎn)寫 property value shorthand

let first = "Bob";
let last = "Dylan";
let singer = { first, last };
console.log(singer.first + " " + singer.last); // Bob Dylan

這對(duì)于經(jīng)常使用對(duì)象作為配置屬性參數(shù)的苦主來說,算個(gè)小小的撫慰了。估計(jì)重復(fù)添加同一屬性會(huì)報(bào)錯(cuò)吧,沒有驗(yàn)證。

3.方法定義 Method definitions

let obj = {
    myMethod(arg0, arg1) {
        ...
    }
};

避免了在對(duì)象定義中出現(xiàn)function關(guān)鍵字,更加清晰明確地分離出函數(shù)的三種用途。

4.賦值解構(gòu) Destructuring

let singer = { first: "Bob", last: "Dylan" };
let { first: f, last: l } = singer; // 相當(dāng)于 f = "Bob", l = "Dylan"

依然是為了方便。以后代碼頭部的「變量定義區(qū)域」不會(huì)有太多行了。

數(shù)組也是可以的,下面這個(gè)例子特別棒:

let [all, year, month, day] =
    /^(ffffdd)-(dd)-(dd)$/.exec("2014-08-31");

let [x, y] = [1, 2, 3]; // x = 1, y = 2

當(dāng)然也可以這樣,但有些……:

function f([x]) {...} // 參數(shù)定義
f(["Blonde on Blonde"]);

下面是幾種錯(cuò)誤用法(Refutable):

let { a: x, b: y } = {a: 3}; // TypeError
let [x, y] = ["a"]; // TypeError

更重要的是,支持默認(rèn)值,在形式不匹配或目標(biāo)值undefined時(shí)有效:

let { a: x, b: y=5 } = {a: 3, b: undefined }; // x = 3, y = 5
let [x, y="b"] = ["a"]; // x = "a", y = "b"

5.函數(shù)的多項(xiàng)返回值 Multiple return values

function findSong(songs, songTitle) {
    for (let trackNumber = 0; trackNumber < songs.length; trackNumber++) {
        let song = songs[trackNumber];
        if(songTitle ===song.title) {
            return {song, trackNumber};
        }
    }
    return {song: undefined, trackNumber: -1}
}

let songList = ["Tombstone blues", "Don"t think twice", "North country girl"];

let {song, trackNumber} = findSong(songList, "North country girl"); // song = "North country girl", trackNumber = 2;

因?yàn)橘x值解構(gòu),所以也可以這樣:

let {song} = findSong(...);
let {trackNumber} = findSong(...);
let {trackNumber, song} = findSong(...); // 變量順序不重要

其實(shí)就是返回個(gè)對(duì)象。

但也有個(gè)問題,變量名一定要與函數(shù)返回對(duì)象的屬性名相同,這可以會(huì)是一個(gè)別扭點(diǎn)。

6.函數(shù)參數(shù) - 默認(rèn)值

function findArtist(name="", genre="") {
    ...
}

沒什么好說的,以后不用再寫var option = option || {}了。

7.函數(shù)參數(shù) - 參數(shù)打包 Rest parameters

function createArtistProfile(name, ...details) {
    .. // details是個(gè)數(shù)組
}

所以,以后也不需要arguments了。不過,看例子只是「1,rest」,不知可不可以「1,2,3,rest」。

8.函數(shù)參數(shù) - 數(shù)組展開 Spread parameters

Math.max(...[1,11,111]); // 111

算是參數(shù)打包的逆操作,以后不用寫[1,2,3].apply(Math.max)這類代碼了。

9.函數(shù)參數(shù) - 指名參數(shù) Named parameters

function func(arg0, {opt1, opt2}) {
    return [opt1, opt2];
}

func(0, {opt1: "a", opt2: "b"}) // ["a", "b"]

同樣是通過對(duì)象帶來的變化。有個(gè)復(fù)雜點(diǎn)的例子:

class Entries {
    // ...
    selectEntries({ from = 0, to = this.length } = {}) {
    // Long: { from: from=0, to: to=this.length }

        // Use `from` and `to`
    }
}

let entries = new Entries();
entries.selectEntries({ from: 5, to: 15 });
entries.selectEntries({ from: 5 });
entries.selectEntries({ to: 15 });

指名參數(shù)+賦值解構(gòu)+默認(rèn)參數(shù),看著反而有點(diǎn)混亂了……自由度大自然帶來閱讀難度的上升,這又是一個(gè)權(quán)衡點(diǎn)。

10.胖箭頭函數(shù) Arrow functions

let bob = {
    name: "Bob Dylan",

    holdConcert: function (songList) {
        songList.forEach(song => {
            console.log(this.name + " sang " + song)
        });
    }
}

這里形式上借鑒了CoffeeScript里「fat arrow」(ES6對(duì)執(zhí)行和內(nèi)存上有優(yōu)化)。Arrow functions主要做了兩件事:

簡(jiǎn)化了代碼形式,默認(rèn)return表達(dá)式結(jié)果。

自動(dòng)綁定語義this,即定義函數(shù)時(shí)的this。如上面例子中,forEach的匿名函數(shù)參數(shù)中用到的this。

來看幾個(gè)例子:

let squares = [ 1, 2, 3 ].map(x => x * x);

x => x + this.y
// 相當(dāng)于
function(x) { return x + this.y }.bind(this)
// 但胖箭頭在執(zhí)行效率上會(huì)更高

胖箭頭函數(shù)與正常函數(shù)的區(qū)別:

胖箭頭在創(chuàng)建時(shí)即綁定this(lexical this);正常函數(shù)的this是在執(zhí)行時(shí)動(dòng)態(tài)傳入的(dynamic this)。

胖箭頭沒有內(nèi)部方法[[Construct]]和屬性原型,所以new (() => {})是會(huì)報(bào)錯(cuò)的。

胖箭頭沒有arguments變量。

這樣,以后在定義方法/函數(shù)時(shí),就有了清晰的選擇:

定義子程序(subroutine),用胖箭頭,自動(dòng)獲得語義this。

定義方法(method),用正常函數(shù),動(dòng)態(tài)this。而且可以用方法定義特性簡(jiǎn)寫代碼,避免function關(guān)鍵字出現(xiàn)。

11.字符串模板 Template strings

templateHandler`Hello ${first} ${last}!`

${first}這樣的結(jié)構(gòu)在Ruby的字符串處理很常見,first是動(dòng)態(tài)替換的部分。templateHandler是替換后的處理函數(shù)。

當(dāng)然也可以不要handler,那就僅僅是模板替換了:

if(x > MAX) {
    throw new Error(`At most ${MAX} allowed: $(x)!`);
}

Template strings支持多行,其間的文本也不會(huì)被轉(zhuǎn)碼:

var str = String.raw`This is a text
with multiple lines.

Escapes are not interpreted,

 is not a newline.`;

結(jié)合不同的handler,用法多樣,比如正則:

let str = "Bob Dylan - 2009 - Together Through Life";
let albumInfo = str.match(XRegExp.rx`
    ^(?[^/]+ ) - (?d{4}) - (?[^/]+)$
`);
console.log(albumInfo.year); // 2009

12.迭代器 Iterators

稍微熟悉函數(shù)式編程(Python,Ruby也可以)的朋友對(duì)著這個(gè)概念應(yīng)該都不陌生。ES6參考了Python的設(shè)計(jì),迭代器有個(gè)next方法,調(diào)用會(huì)返回:

返回迭代對(duì)象的一個(gè)元素:{ done: false, value: elem }

如果已到迭代對(duì)象的末端:{done: true[, value: retVal] }

上面第二種情況中的條件返回部分是為了遞歸調(diào)用生成器而設(shè)計(jì)的(迭代器其實(shí)是生成器的應(yīng)用之一),具體說明參見這篇文章的對(duì)應(yīng)部分。

下例實(shí)現(xiàn)了一個(gè)數(shù)組的迭代器:

function createArrayIterator(arr) {
    let index = 0;
    return {
        next() {
            if (index < arr.length) {
                return { done: false, value: arr[index++]  };
            else {
                return { done: true }
            }
        }
    }
}

let arr = [1,2,3];
let iter = createArrayIterator(arr);
console.log(iter.next());  // 1
console.log(iter.next());  // 2

在ES6中,可迭代數(shù)據(jù)結(jié)構(gòu)(比如數(shù)組)都必須實(shí)現(xiàn)一個(gè)名為Symbol.iterator的方法,該方法返回一個(gè)該結(jié)構(gòu)元素的迭代器。注意,Symbol.iterator是一個(gè)Symbol,Symbol是ES6新加入的原始值類型。

針對(duì)可迭代的數(shù)據(jù)結(jié)構(gòu),ES6還引入了一個(gè)新的遍歷方法 for-of。再舉個(gè)例子,改造下上例中的createArrayIterator

function createArrayIterator(arr) {
    let index = 0;
    return {
        [Symbol.iterator]() {
            return this; // 因?yàn)楸旧砭褪莻€(gè)迭代器
        },
        next() {
            ...
        }
    }
}

let arr = [1, 2, 3];
for(x of createArrayIterator(arr)) { // 注意看
    console.log(x);
}

當(dāng)然,ES6中的數(shù)組本身就是可迭代的,上例僅僅是為了展示而已。

13.生成器 Generators

ES6的生成器同樣借鑒了Python,通過操作符yield掛起、繼續(xù)

生成器的寫法比較怪異,使用了關(guān)鍵字function*

function* generatorFunction() {
    yield 1;
    yield 2;
}

生成器返回一個(gè)對(duì)象,用來控制生成器執(zhí)行,這個(gè)對(duì)象是可迭代的:

let genObj = generatorFunction();
genObj.next(); // { done: false, value: 1 }
genObj.next(); // { done: false, value: 2 }
genObj.next(); // { done: true }

下面這個(gè)例子演示了可遞歸調(diào)用的生成器,用到了操作符yield*

function* iterTree(tree) {
    if (Array.isArray(tree)) {
        for (let i = 0; i < tree.length; i++) {
            yield* iterTree(tree[i]);  // (*)
        }
    } else {
        yield tree;
    }
}

yield*會(huì)交出(yield)全部迭代對(duì)象,而不僅僅是一個(gè)元素值。原話是「yield* in line (*) yields everything that is yielded by the iterable that is its operand. 」

yield*還可以傳遞返回值。如:

let result1 = yield* step(); // step也是個(gè)generator

這個(gè)例子不太好,或者說,ES6的這部分實(shí)現(xiàn)有點(diǎn)繁瑣,需要更多示例才能理解這個(gè)特性。

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/87626.html

相關(guān)文章

  • ECMAScript 6特性印象之二:面對(duì)對(duì)象和模塊化

    摘要:本文參考了以下文章之前的文章新特性印象之一新語法面對(duì)對(duì)象關(guān)鍵字看上面例子就能明白。定義類的,配合創(chuàng)建新對(duì)象。繼承非構(gòu)造器對(duì)象的原型是。錯(cuò)誤檢查繼承的目標(biāo)一定要是個(gè)對(duì)象或者。的構(gòu)造器是可改寫,但不可枚舉。引入了一個(gè)標(biāo)簽,負(fù)責(zé)載入模塊。 本文參考了以下文章/PPT: Use ECMAScript 6 today Ecmascript 6 Whats next for Javascrip...

    darryrzhong 評(píng)論0 收藏0
  • JavaScript 簡(jiǎn)史

    摘要:正大力推進(jìn),網(wǎng)景通訊公司即將與他們達(dá)成一項(xiàng)協(xié)議,讓可以用在瀏覽器上。年月,網(wǎng)景通訊公司和達(dá)成協(xié)議將被重新命名為,它將會(huì)作為瀏覽器中小型客戶端任務(wù)的一種腳本語言,同時(shí)將會(huì)被提升為一種更大的開發(fā)富組件的專業(yè)工具。 本文轉(zhuǎn)載自:眾成翻譯譯者:網(wǎng)絡(luò)埋伏紀(jì)事審校: 為之漫筆鏈接:http://www.zcfy.cc/article/2389原文:https://auth0.com/blog/a-...

    pubdreamcc 評(píng)論0 收藏0
  • 印象最深的一個(gè)bug:sessionStorage緩存在移動(dòng)端失效

    摘要:移動(dòng)端緩存失效是我印象最深的一個(gè)之一,為啥呢,因?yàn)檫@個(gè)問題導(dǎo)致我加班到很晚。的生命周期是僅在當(dāng)前會(huì)話下有效。引入了一個(gè)瀏覽器窗口的概念,是在同源的窗口中始終存在的數(shù)據(jù)。無bug,不程序:作為程序員的我,不是修bug就是在寫bug的路上。  移動(dòng)端sessionStorage緩存失效是我印象最深的一個(gè)bug之一,為啥呢,因?yàn)檫@個(gè)問題導(dǎo)致我加班到很晚。在現(xiàn)在看來就是一個(gè)簡(jiǎn)單的概念問題。在我剛工作...

    yuxue 評(píng)論0 收藏0
  • React 、 ES6 - 介紹(第一部分)

    摘要:下一步我們將結(jié)果輸出到文件。這是我們用編寫的第一個(gè)非常簡(jiǎn)單的組建。使用將創(chuàng)建的組建導(dǎo)出以便在其它地方能夠正常導(dǎo)入使用。 這是React和ECMAScript6結(jié)合使用系列文章的第一篇。 本文出自從零到壹全棧部落 下面是所有系列文章章節(jié)的鏈接: React 、 ES6 - 介紹(第一部分) React類、ES7屬性初始化(第二部分) React類,方法綁定(第三部分) ES6中Reac...

    pingink 評(píng)論0 收藏0
  • 【譯】ECMAScript文檔---序言及1-6章(上)

    摘要:隨后,它出現(xiàn)在公司之后的瀏覽器,以及從微軟從起發(fā)布的所有瀏覽器上。標(biāo)準(zhǔn)的第版在年月的大會(huì)上被表決接受。第版在年月底大會(huì)上被采納。 前言 ??本系列譯文的初衷旨在希望更多人能夠了解關(guān)于JS的一些基本概念,遇到原理性的問題時(shí)多去翻翻文檔,而不是在社區(qū)無休止的重復(fù)提出某些在文檔中能夠非常方便快捷就能找到的東西。 ??精力和水平有限,所以暫時(shí)只打算嘗試翻譯前面幾章概括性的介紹,同時(shí)后面的章節(jié)大...

    wind3110991 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<