ES6 Function類型

相比ES5,ES6 允許為函數(shù)的參數(shù)設(shè)置默認值蛋叼。

即直接寫在參數(shù)定義的后面晶密。

function log(x, y = 'World') {

    console.log(x, y);

}

log('Hello') // Hello World

log('Hello', 'China') // Hello China

log('Hello', '') // Hello





ES6 引入 rest 參數(shù)(形式為 “... 變量名 ” )虐秋,用于獲取函數(shù)的多余參數(shù),這樣就不需要使用 arguments 對象了努潘。 rest 參數(shù)搭配的變量是一個數(shù)組诽偷,該變量將

多余的參數(shù)放入數(shù)組中。

function add(...values) {

    let sum = 0;

    for (var val of values) {

        sum += val;

    }

    return sum;

}

add(2, 5, 3) // 10




上面代碼的 add 函數(shù)是一個求和函數(shù)疯坤,利用 rest 參數(shù)报慕,可以向該函數(shù)傳入任意數(shù)目的參數(shù)。

下面是一個 rest 參數(shù)代替 arguments 變量的例子压怠。

// arguments 變量的寫法

function sortNumbers() {

    return Array.prototype.slice.call(arguments).sort();

    }

// rest 參數(shù)的寫法

const sortNumbers = (...numbers) => numbers.sort();





上面代碼的兩種寫法眠冈,比較后可以發(fā)現(xiàn), rest 參數(shù)的寫法更自然也更簡潔菌瘫。

rest 參數(shù)中的變量代表一個數(shù)組蜗顽,所以數(shù)組特有的方法都可以用于這個變量。下面是一個利用 rest 參數(shù)改寫數(shù)組 push 方法的例子雨让。

function push(array, ...items) {

    items.forEach(function(item) {

        array.push(item);

        console.log(item);

    });

}

var a = [];

push(a, 1, 2, 3)





注意雇盖, rest 參數(shù)之后不能再有其他參數(shù)(即只能是最后一個參數(shù)),否則會報錯栖忠。

// 報錯

function f(a, ...b, c) {

// ...

}

函數(shù)的 length 屬性崔挖,不包括 rest 參數(shù)贸街。

(function(a) {}).length // 1

(function(...a) {}).length // 0

(function(a, ...b) {}).length // 1





擴展運算符

擴展運算符( spread )是三個點(...)。它好比 rest 參數(shù)的逆運算狸相,將一個數(shù)組轉(zhuǎn)為用逗號分隔的參數(shù)序列薛匪。

console.log(...[1, 2, 3])

// 1 2 3

console.log(1, ...[2, 3, 4], 5)

// 1 2 3 4 5

[...document.querySelectorAll('div')]

// [div, div, div]

該運算符主要用于函數(shù)調(diào)用。

function push(array, ...items) {

    array.push(...items);

}

function add(x, y) {

    return x + y;

}

var numbers = [4, 38];

add(...numbers) // 42

上面代碼中卷哩,array.push(...items)和add(...numbers)這兩行蛋辈,都是函數(shù)的調(diào)用,它們的都使用了擴展運算符将谊。該運算符將一個數(shù)組冷溶,變?yōu)閰?shù)序

列。





擴展運算符與正常的函數(shù)參數(shù)可以結(jié)合使用尊浓,非常靈活逞频。

function f(v, w, x, y, z) { }

var args = [0, 1];

f(-1, ...args, 2, ...[3]);


替代數(shù)組的 apply 方法

由于擴展運算符可以展開數(shù)組,所以不再需要apply方法栋齿,將數(shù)組轉(zhuǎn)為函數(shù)的參數(shù)了苗胀。

// ES5 的寫法

function f(x, y, z) {

// ...

}

var args = [0, 1, 2];

f.apply(null, args);

// ES6 的寫法

function f(x, y, z) {

// ...

}

var args = [0, 1, 2];

f(...args);



下面是擴展運算符取代apply方法的一個實際的例子,應(yīng)用Math.max方法瓦堵,簡化求出一個數(shù)組最大元素的寫法基协。

// ES5 的寫法

Math.max.apply(null, [14, 3, 77])

// ES6 的寫法

Math.max(...[14, 3, 77])

// 等同于

Math.max(14, 3, 77);

上面代碼表示,由于 JavaScript 不提供求數(shù)組最大元素的函數(shù)菇用,所以只能套用Math.max函數(shù)澜驮,將數(shù)組轉(zhuǎn)為一個參數(shù)序列,然后求最大值惋鸥。有了擴展運算符以后杂穷,就可以直接用Math.max了。




另一個例子是通過push函數(shù)卦绣,將一個數(shù)組添加到另一個數(shù)組的尾部耐量。

// ES5 的寫法

var arr1 = [0, 1, 2];

var arr2 = [3, 4, 5];

Array.prototype.push.apply(arr1, arr2);

// ES6 的寫法

var arr1 = [0, 1, 2];

var arr2 = [3, 4, 5];

arr1.push(...arr2);

上面代碼的 ES5 寫法中,push方法的參數(shù)不能是數(shù)組滤港,所以只好通過apply方法變通使用push方法廊蜒。有了擴展運算符,就可以直接將數(shù)組傳入push方法蜗搔。

下面是另外一個例子劲藐。

// ES5

new (Date.bind.apply(Date, [null, 2015, 1, 1]))

// ES6

new Date(...[2015, 1, 1]);



擴展運算符的應(yīng)用

( 1 )合并數(shù)組

擴展運算符提供了數(shù)組合并的新寫法。

// ES5

[1, 2].concat(more)

// ES6

[1, 2, ...more]

var arr1 = ['a', 'b'];

var arr2 = ['c'];

var arr3 = ['d', 'e'];

// ES5 的合并數(shù)組

arr1.concat(arr2, arr3);

// [ 'a', 'b', 'c', 'd', 'e' ]

// ES6 的合并數(shù)組

[...arr1, ...arr2, ...arr3]

// [ 'a', 'b', 'c', 'd', 'e' ]



( 2 )與解構(gòu)賦值結(jié)合

擴展運算符可以與解構(gòu)賦值結(jié)合起來樟凄,用于生成數(shù)組聘芜。

// ES5

a = list[0], rest = list.slice(1)

// ES6

[a, ...rest] = list

下面是另外一些例子。

const [first, ...rest] = [1, 2, 3, 4, 5];

first // 1

rest // [2, 3, 4, 5]

const [first, ...rest] = [];

first // undefined

rest // []:

const [first, ...rest] = ["foo"];

first // "foo"

rest // []




如果將擴展運算符用于數(shù)組賦值缝龄,只能放在參數(shù)的最后一位汰现,否則會報錯挂谍。

const [...butLast, last] = [1, 2, 3, 4, 5];

// 報錯

const [first, ...middle, last] = [1, 2, 3, 4, 5];

// 報錯




( 3 )函數(shù)的返回值

JavaScript 的函數(shù)只能返回一個值,如果需要返回多個值瞎饲,只能返回數(shù)組或?qū)ο罂谛稹U展運算符提供了解決這個問題的一種變通方法。

var dateFields = readDateFields(database);

var d = new Date(...dateFields);

上面代碼從數(shù)據(jù)庫取出一行數(shù)據(jù)嗅战,通過擴展運算符妄田,直接將其傳入構(gòu)造函數(shù)Date。



( 4 )字符串

擴展運算符還可以將字符串轉(zhuǎn)為真正的數(shù)組驮捍。

[...'hello']

// [ "h", "e", "l", "l", "o" ]

上面的寫法疟呐,有一個重要的好處,那就是能夠正確識別 32 位的 Unicode 字符东且。

'x\uD83D\uDE80y'.length // 4

[...'x\uD83D\uDE80y'].length // 3

上面代碼的第一種寫法启具, JavaScript 會將 32 位 Unicode 字符,識別為 2 個字符珊泳,采用擴展運算符就沒有這個問題鲁冯。因此,正確返回字符串長度的函數(shù)色查,

可以像下面這樣寫薯演。

function length(str) {

    return [...str].length;

}

length('x\uD83D\uDE80y') // 3




凡是涉及到操作 32 位 Unicode 字符的函數(shù),都有這個問題秧了。因此涣仿,最好都用擴展運算符改寫。

let str = 'x\uD83D\uDE80y';

str.split('').reverse().join('')

// 'y\uDE80\uD83Dx'

[...str].reverse().join('')

// 'y\uD83D\uDE80x'

上面代碼中示惊,如果不用擴展運算符,字符串的reverse操作就不正確愉镰。



( 5 )實現(xiàn)了 Iterator 接口的對象

任何 Iterator 接口的對象米罚,都可以用擴展運算符轉(zhuǎn)為真正的數(shù)組。

var nodeList = document.querySelectorAll('div');

var array = [...nodeList];

上面代碼中丈探,querySelectorAll方法返回的是一個nodeList對象录择。它不是數(shù)組,而是一個類似數(shù)組的對象碗降。這時隘竭,擴展運算符可以將其轉(zhuǎn)為真正的數(shù)

組,原因就在于NodeList對象實現(xiàn)了 Iterator 接口讼渊。

對于那些沒有部署 Iterator 接口的類似數(shù)組的對象动看,擴展運算符就無法將其轉(zhuǎn)為真正的數(shù)組。

let arrayLike = {

'0': 'a',

'1': 'b',

'2': 'c',

length: 3

};

// TypeError: Cannot spread non-iterable object.

let arr = [...arrayLike];

上面代碼中爪幻,arrayLike是一個類似數(shù)組的對象菱皆,但是沒有部署 Iterator 接口须误,擴展運算符就會報錯。這時仇轻,可以改為使用Array.from方法

將arrayLike轉(zhuǎn)為真正的數(shù)組京痢。



( 6 ) Map 和 Set 結(jié)構(gòu), Generator 函數(shù)

擴展運算符內(nèi)部調(diào)用的是數(shù)據(jù)結(jié)構(gòu)的 Iterator 接口篷店,因此只要具有 Iterator 接口的對象祭椰,都可以使用擴展運算符,比如 Map 結(jié)構(gòu)疲陕。

let map = new Map([

    [1, 'one'],

    [2, 'two'],

    [3, 'three'],

]);

let arr = [...map.keys()]; // [1, 2, 3]

Generator 函數(shù)運行后方淤,返回一個遍歷器對象,因此也可以使用擴展運算符鸭轮。

var go = function*(){

yield 1;

yield 2;

yield 3;

};

[...go()] // [1, 2, 3]

上面代碼中臣淤,變量go是一個 Generator 函數(shù),執(zhí)行后返回的是一個遍歷器對象窃爷,對這個遍歷器對象執(zhí)行擴展運算符邑蒋,就會將內(nèi)部遍歷得到的值,轉(zhuǎn)為一

個數(shù)組按厘。

如果對沒有iterator接口的對象医吊,使用擴展運算符,將會報錯逮京。

var obj = {a: 1, b: 2};

let arr = [...obj]; // TypeError: Cannot spread non-iterable object



?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末卿堂,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子懒棉,更是在濱河造成了極大的恐慌草描,老刑警劉巖,帶你破解...
    沈念sama閱讀 221,695評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件策严,死亡現(xiàn)場離奇詭異穗慕,居然都是意外死亡,警方通過查閱死者的電腦和手機妻导,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,569評論 3 399
  • 文/潘曉璐 我一進店門逛绵,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人倔韭,你說我怎么就攤上這事术浪。” “怎么了寿酌?”我有些...
    開封第一講書人閱讀 168,130評論 0 360
  • 文/不壞的土叔 我叫張陵胰苏,是天一觀的道長。 經(jīng)常有香客問我份名,道長碟联,這世上最難降的妖魔是什么妓美? 我笑而不...
    開封第一講書人閱讀 59,648評論 1 297
  • 正文 為了忘掉前任,我火速辦了婚禮鲤孵,結(jié)果婚禮上壶栋,老公的妹妹穿的比我還像新娘。我一直安慰自己普监,他們只是感情好贵试,可當(dāng)我...
    茶點故事閱讀 68,655評論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著凯正,像睡著了一般毙玻。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上廊散,一...
    開封第一講書人閱讀 52,268評論 1 309
  • 那天桑滩,我揣著相機與錄音,去河邊找鬼允睹。 笑死运准,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的缭受。 我是一名探鬼主播胁澳,決...
    沈念sama閱讀 40,835評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼米者!你這毒婦竟也來了韭畸?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,740評論 0 276
  • 序言:老撾萬榮一對情侶失蹤蔓搞,失蹤者是張志新(化名)和其女友劉穎胰丁,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體喂分,經(jīng)...
    沈念sama閱讀 46,286評論 1 318
  • 正文 獨居荒郊野嶺守林人離奇死亡隘马,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,375評論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了妻顶。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,505評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡蜒车,死狀恐怖讳嘱,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情酿愧,我是刑警寧澤沥潭,帶...
    沈念sama閱讀 36,185評論 5 350
  • 正文 年R本政府宣布,位于F島的核電站嬉挡,受9級特大地震影響钝鸽,放射性物質(zhì)發(fā)生泄漏汇恤。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,873評論 3 333
  • 文/蒙蒙 一拔恰、第九天 我趴在偏房一處隱蔽的房頂上張望因谎。 院中可真熱鬧,春花似錦颜懊、人聲如沸财岔。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,357評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽匠璧。三九已至,卻和暖如春咸这,著一層夾襖步出監(jiān)牢的瞬間夷恍,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,466評論 1 272
  • 我被黑心中介騙來泰國打工媳维, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留酿雪,地道東北人。 一個月前我還...
    沈念sama閱讀 48,921評論 3 376
  • 正文 我出身青樓侨艾,卻偏偏與公主長得像执虹,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子唠梨,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,515評論 2 359

推薦閱讀更多精彩內(nèi)容

  • 函數(shù)參數(shù)的默認值 基本用法 在ES6之前袋励,不能直接為函數(shù)的參數(shù)指定默認值,只能采用變通的方法当叭。 上面代碼檢查函數(shù)l...
    呼呼哥閱讀 3,402評論 0 1
  • 函數(shù)參數(shù)的默認值 基本用法 在ES6之前感局,不能直接為函數(shù)的參數(shù)指定默認值掠兄,只能采用變通的方法。 上面代碼檢查函數(shù)l...
    陳老板_閱讀 449評論 0 1
  • 三,字符串?dāng)U展 3.1 Unicode表示法 ES6 做出了改進粘都,只要將碼點放入大括號,就能正確解讀該字符羽德。有了這...
    eastbaby閱讀 1,539評論 0 8
  • 1.函數(shù)參數(shù)的默認值 (1).基本用法 在ES6之前泥耀,不能直接為函數(shù)的參數(shù)指定默認值,只能采用變通的方法讥裤。
    趙然228閱讀 693評論 0 0
  • [TOC] 參考阮一峰的ECMAScript 6 入門參考深入淺出ES6 let和const let和const都...
    郭子web閱讀 1,783評論 0 1