ES6學(xué)習(xí) 第七章 函數(shù)的擴(kuò)展

前言

本章介紹函數(shù)的擴(kuò)展。有些不常用的知識(shí)了解即可疯汁。
本章原文鏈接:函數(shù)的擴(kuò)展寥院。

函數(shù)參數(shù)的默認(rèn)值

ES6 允許為函數(shù)的參數(shù)設(shè)置默認(rèn)值,即直接寫在參數(shù)定義的后面涛目。
當(dāng)函數(shù)形參沒(méi)有被賦值時(shí)秸谢,才會(huì)將默認(rèn)值賦值給函數(shù)參數(shù)。

// 默認(rèn)值直接寫在行參后面
function sampleFn(sample = 0, sample1 = 0) {
  return sample + sample1;
}

注意:

  • 參數(shù)變量是默認(rèn)聲明的霹肝,所以不能用letconst再次聲明估蹄。
  • 使用參數(shù)默認(rèn)值時(shí),函數(shù)不能有同名參數(shù)沫换。
  • 參數(shù)默認(rèn)值是惰性求值的臭蚁。
  • 函數(shù)的默認(rèn)值指定后,函數(shù)length屬性返回的是沒(méi)有指定默認(rèn)值的參數(shù)的個(gè)數(shù)讯赏。
  • 參數(shù)的默認(rèn)值一旦設(shè)定垮兑,函數(shù)進(jìn)行聲明初始化時(shí),參數(shù)會(huì)形成一個(gè)單獨(dú)的作用域(context)漱挎。
// 默認(rèn)值直接寫在行參后面
function sampleFn(sample = 0, sample1 = 0,sample = 1) { // 不能有同名參數(shù)

  let sample = 1; // 不能再次聲明

  return sample + sample1;
}

注意:通常情況下系枪,定義了默認(rèn)值的參數(shù),應(yīng)該是函數(shù)的尾參數(shù)磕谅。也就是放在最后面私爷。

解構(gòu)賦值默認(rèn)值

// 函數(shù)的默認(rèn)值與結(jié)構(gòu)賦值的默認(rèn)值可以結(jié)合使用
function sampleFn({ sample = 0, sample1 = 0 } = {}) { // 函數(shù)參數(shù)默認(rèn)值
  return sample + sample1;
}

console.log(sampleFn({ sample: 23, sample1: 33 })); // 56 參數(shù)需對(duì)應(yīng)解構(gòu)賦值的類型

作用域

當(dāng)函數(shù)參數(shù)設(shè)置了默認(rèn)值,函數(shù)進(jìn)行聲明初始化時(shí)膊夹,函數(shù)參數(shù)會(huì)生成一個(gè)單獨(dú)的作用域衬浑,等到初始化結(jié)束,該作用域就會(huì)消失放刨。而且該行為只在函數(shù)參數(shù)指定了默認(rèn)值才會(huì)出現(xiàn)工秩。

let sample = 1;

/* 
    在聲明的時(shí)候出現(xiàn)單獨(dú)作用域
  在這個(gè)作用域中,變量沒(méi)有定義,于是指向外層變量
    函數(shù)調(diào)用時(shí)助币,函數(shù)內(nèi)部變量影響不到默認(rèn)值變量
*/
function sampleFn(sample1 = sample) { 
  let sample = 2;
  console.log(sample1);
  return sample1;
}

sampleFn() // 1

rest 參數(shù)

ES6 引入 **rest 參數(shù) **浪听,用于獲取函數(shù)的多余參數(shù)。
arguments 對(duì)象是類數(shù)組奠支,rest 參數(shù)是真正的數(shù)組馋辈。

形式為:...變量名抚芦,函數(shù)的最后一個(gè)命名參數(shù)以...為前綴倍谜。

// 下面例子中 ...values 為 rest參數(shù) ,用于獲取多余參數(shù)
const sample = function (title, ...values) {
  let sample = values.filter(
    (item) => {
      return item % 2 === 0;
    }
  )

  return (title + sample);
}

console.log(sample("求偶數(shù)", 1, 2, 6, 2, 1));  // 求偶數(shù) 2, 6, 2

注意:rest參數(shù) 只能是函數(shù)的最后一個(gè)參數(shù)叉抡,函數(shù)的length不包括rest參數(shù)

嚴(yán)格模式

在JavaScript中尔崔,只要在函數(shù)中的嚴(yán)格模式,會(huì)作用于函數(shù)參數(shù)和函數(shù)體褥民。
ES2016 規(guī)定只要函數(shù)參數(shù)使用了默認(rèn)值季春、解構(gòu)賦值、或者擴(kuò)展運(yùn)算符消返,那么函數(shù)內(nèi)部就不能顯式設(shè)定為嚴(yán)格模式载弄,否則會(huì)報(bào)錯(cuò)。

function sample() { // 參數(shù)使用默認(rèn)值撵颊、解構(gòu)賦值宇攻、擴(kuò)展運(yùn)算符 
  'use strict'; // 開啟嚴(yán)格模式
}

name 屬性

函數(shù)的name屬性,返回該函數(shù)的函數(shù)名倡勇。

function sample() { };
let sample1 = function () { };
function sample2() {};

console.log(sample.name); // sample
console.log(sample1.name); //  sample1 

// bound sample2  使用了 bind 方法逞刷,輸出會(huì)有bound前綴
console.log(sample2.bind({}).name); 
console.log((new Function).name); // anonymous  構(gòu)造函數(shù)的name值為 anonymous

箭頭函數(shù)

簡(jiǎn)單介紹

ES 6 新增一種函數(shù)定義方法,使用箭頭連接參數(shù)列與函數(shù)題妻熊。
箭頭函數(shù)相當(dāng)于匿名函數(shù)夸浅,并且簡(jiǎn)化了函數(shù)定義,箭頭函數(shù)沒(méi)有prototype扔役。

// 普通函數(shù)
let sample = function (item) {
  return item;
};

// 上面函數(shù)等同于下面函數(shù)

// 使用箭頭函數(shù)
let sample = (item) => { return item}; // 箭頭函數(shù)

箭頭函數(shù)簡(jiǎn)寫

沒(méi)錯(cuò)帆喇,箭頭函數(shù)還可以簡(jiǎn)寫

  1. 當(dāng)參數(shù)只有一個(gè)時(shí),可以省略箭頭左邊的括號(hào)亿胸,但沒(méi)有參數(shù)時(shí)番枚,括號(hào)不可以省略。
  2. 當(dāng)函數(shù)體只有一個(gè)表達(dá)式時(shí)损敷,可省略箭頭右邊的大括號(hào)葫笼,但同時(shí)必須省略return語(yǔ)句 并寫在一行。
  3. 當(dāng)函數(shù)體分多于一條語(yǔ)句拗馒,就要使用大括號(hào)將它們括起來(lái)路星,并且使用return語(yǔ)句返回。
// 下面幾種函數(shù)寫法都相同
let sample = function (item) {
  return item;
};

let sample = (item) => { return item}; // 箭頭函數(shù) 不省略

let sample = item => { return item}; // 省略左邊圓括號(hào)

let sample = (item) => item; // 省略右邊大括號(hào)和 return

let sample = item => item; // ?省略左邊圓括號(hào)和右邊花括號(hào)和return

// 如果不需要返回值的特殊情況
let sample = item => void item;
console.log(sample()); // undefined

注意點(diǎn)

  • 箭頭函數(shù) 的 This 默認(rèn)指向定義它的作用域的 This
  • 箭頭函數(shù) 不能用作構(gòu)造函數(shù)洋丐。
  • 箭頭函數(shù) 不可以使用 arguments 對(duì)象呈昔,該對(duì)象在函數(shù)體內(nèi)不存在。
  • 箭頭函數(shù) 不可以使用yield命令友绝,也就不能作為 Generator 函數(shù)堤尾。

箭頭函數(shù)的this

箭頭函數(shù) 會(huì)繼承自己定義時(shí)所處的作用域鏈上一層的this
箭頭函數(shù) this在定義的時(shí)候已經(jīng)確定了迁客,所以箭頭函數(shù)this不會(huì)改變郭宝。
使用 call()apply() 方法時(shí),也不能重新給箭頭函數(shù)綁定this掷漱,bing()方法無(wú)效粘室。

window.sample = "window 內(nèi) ";

function sampleFn() {
  let thiz = this;
  let sample = "sampleFn 內(nèi) ";

  let sampleObj = {
    sample: "sampleObj 內(nèi) ",

    // 普通函數(shù)
    sampleFn1: function () {
      console.log(thiz === this);
      console.log(this.sample);
    },

    // 箭頭函數(shù)
    sampleFn2: () => {
      // 箭頭函數(shù)的作用域?yàn)?sampleObj 上一層為 sampleFn
      console.log(thiz === this); //箭頭函數(shù)的 this  
      console.log(this.sample);
    }
  }

  sampleObj.sampleFn1();  // false, sampleObj 內(nèi) 
  sampleObj.sampleFn2();  // true, window 內(nèi)
}

sampleFn();

尾調(diào)用優(yōu)化

有兩個(gè)概念

  1. 尾調(diào)用
    尾調(diào)用(Tail Call)是函數(shù)式編程的一個(gè)重要概念,就是指某個(gè)函數(shù)的最后一步是調(diào)用另一個(gè)函數(shù)卜范。

  2. 尾遞歸
    函數(shù)調(diào)用自身衔统,稱為遞歸。如果尾調(diào)用自身海雪,就稱為尾遞歸锦爵。

ES6 明確規(guī)定,所有 ECMAScript 的實(shí)現(xiàn)奥裸,都必須部署“尾調(diào)用優(yōu)化”险掀。
這就是說(shuō),ES6 中只要使用尾遞歸刺彩,就不會(huì)發(fā)生棧溢出(或者層層遞歸造成的超時(shí))迷郑,相對(duì)節(jié)省內(nèi)存。

這是什么意思呢创倔?

尾調(diào)用的作用嗡害,在原文中是這樣寫的:

我們知道,函數(shù)調(diào)用會(huì)在內(nèi)存形成一個(gè)“調(diào)用記錄”畦攘,又稱“調(diào)用幀”(call frame)霸妹,保存調(diào)用位置和內(nèi)部變量等信息。如果在函數(shù)A的內(nèi)部調(diào)用函數(shù)B知押,那么在A的調(diào)用幀上方叹螟,還會(huì)形成一個(gè)B的調(diào)用幀。等到B運(yùn)行結(jié)束台盯,將結(jié)果返回到A罢绽,B的調(diào)用幀才會(huì)消失。如果函數(shù)B內(nèi)部還調(diào)用函數(shù)C静盅,那就還有一個(gè)C的調(diào)用幀良价,以此類推。所有的調(diào)用幀,就形成一個(gè)“調(diào)用椕鞴福”(call stack)蚣常。
尾調(diào)用由于是函數(shù)的最后一步操作,所以不需要保留外層函數(shù)的調(diào)用幀痊银,因?yàn)檎{(diào)用位置抵蚊、內(nèi)部變量等信息都不會(huì)再用到了,只要直接用內(nèi)層函數(shù)的調(diào)用幀溯革,取代外層函數(shù)的調(diào)用幀就可以了贞绳。

換種方式解釋吧

函數(shù)被調(diào)用的時(shí)候會(huì)有函數(shù)執(zhí)行上下文被壓入執(zhí)行棧中,直到函數(shù)執(zhí)行結(jié)束鬓照,對(duì)應(yīng)的執(zhí)行上下文才會(huì)出棧熔酷。
在函數(shù)A的內(nèi)部調(diào)用函數(shù)B孤紧,如果函數(shù)B中有對(duì)函數(shù)A中變量的引用豺裆,那么函數(shù)A即使執(zhí)行結(jié)束對(duì)應(yīng)的執(zhí)行上下文也無(wú)法出棧,如果函數(shù)B內(nèi)部還有調(diào)用函數(shù)C那么要等函數(shù)C執(zhí)行完号显,函數(shù)A臭猜、B對(duì)應(yīng)的執(zhí)行上下文才能出棧,以此類推押蚤,執(zhí)行棧中要上一個(gè)函數(shù)(內(nèi)層函數(shù))的執(zhí)行上下文蔑歌,這就是尾調(diào)用優(yōu)化。

// 尾遞歸
function sampleFn(sample) {
  if (sample <= 1) return 1;
  return sampleFn(sample - 1) + sample;
}
sampleFn(2);

注意 :

  • 當(dāng)內(nèi)層函數(shù)沒(méi)有用到外層函數(shù)的內(nèi)部變量的時(shí)候才可以進(jìn)行尾調(diào)用優(yōu)化揽碘。
  • 目前只有 Safari 瀏覽器支持尾調(diào)用優(yōu)化次屠,Chrome 和 Firefox 都不支持。

ES 6 的小修改

函數(shù)參數(shù)尾逗號(hào)

ES2017 允許函數(shù)的最后一個(gè)參數(shù)有尾逗號(hào)(trailing comma)雳刺。
這樣的規(guī)定也使得劫灶,函數(shù)參數(shù)與數(shù)組和對(duì)象的尾逗號(hào)規(guī)則,保持一致了掖桦。

function sampleFn(
  sample1,
  sample2,
  sample3, // 可以在最后一個(gè)參數(shù)后面加 逗號(hào) ','
) {}

toString()修改

Function.prototype.toString()
ES2019 對(duì)函數(shù)實(shí)例的toString()方法做出了修改本昏。明確要求返回一模一樣的原始代碼。
toString()方法返回函數(shù)代碼本身枪汪,ES6前會(huì)省略注釋和空格涌穆。

function sampleFn() {
  // 注釋
}

let sample = sampleFn.toString();
console.log(sample);
//輸出 完全一樣的原始代碼,包括空格與注釋
/*
function sampleFn() {
  // 注釋
}
*/

catch 修改

ES2019 改變了catch語(yǔ)句后面必須攜帶參數(shù)的要求雀久。允許catch語(yǔ)句省略參數(shù)宿稀。

try {
  // ...
} catch { // 不帶參數(shù)
  // ...
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市赖捌,隨后出現(xiàn)的幾起案子祝沸,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,482評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件奋隶,死亡現(xiàn)場(chǎng)離奇詭異擂送,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)唯欣,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,377評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門碳柱,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人章郁,你說(shuō)我怎么就攤上這事车要。” “怎么了萍聊?”我有些...
    開封第一講書人閱讀 152,762評(píng)論 0 342
  • 文/不壞的土叔 我叫張陵问芬,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我寿桨,道長(zhǎng)此衅,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,273評(píng)論 1 279
  • 正文 為了忘掉前任亭螟,我火速辦了婚禮挡鞍,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘预烙。我一直安慰自己墨微,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,289評(píng)論 5 373
  • 文/花漫 我一把揭開白布扁掸。 她就那樣靜靜地躺著翘县,像睡著了一般。 火紅的嫁衣襯著肌膚如雪谴分。 梳的紋絲不亂的頭發(fā)上锈麸,一...
    開封第一講書人閱讀 49,046評(píng)論 1 285
  • 那天,我揣著相機(jī)與錄音狸剃,去河邊找鬼掐隐。 笑死,一個(gè)胖子當(dāng)著我的面吹牛钞馁,可吹牛的內(nèi)容都是我干的虑省。 我是一名探鬼主播,決...
    沈念sama閱讀 38,351評(píng)論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼僧凰,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼探颈!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起训措,我...
    開封第一講書人閱讀 36,988評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤伪节,失蹤者是張志新(化名)和其女友劉穎光羞,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體怀大,經(jīng)...
    沈念sama閱讀 43,476評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡纱兑,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,948評(píng)論 2 324
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了化借。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片潜慎。...
    茶點(diǎn)故事閱讀 38,064評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖蓖康,靈堂內(nèi)的尸體忽然破棺而出铐炫,到底是詐尸還是另有隱情,我是刑警寧澤蒜焊,帶...
    沈念sama閱讀 33,712評(píng)論 4 323
  • 正文 年R本政府宣布倒信,位于F島的核電站,受9級(jí)特大地震影響泳梆,放射性物質(zhì)發(fā)生泄漏鳖悠。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,261評(píng)論 3 307
  • 文/蒙蒙 一鸭丛、第九天 我趴在偏房一處隱蔽的房頂上張望竞穷。 院中可真熱鬧唐责,春花似錦鳞溉、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,264評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至朴恳,卻和暖如春抄罕,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背于颖。 一陣腳步聲響...
    開封第一講書人閱讀 31,486評(píng)論 1 262
  • 我被黑心中介騙來(lái)泰國(guó)打工呆贿, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人森渐。 一個(gè)月前我還...
    沈念sama閱讀 45,511評(píng)論 2 354
  • 正文 我出身青樓做入,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親同衣。 傳聞我的和親對(duì)象是個(gè)殘疾皇子竟块,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,802評(píng)論 2 345

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

  • 1. 函數(shù)的默認(rèn)值 ES6 允許為函數(shù)的參數(shù)設(shè)置默認(rèn)值,即直接寫在參數(shù)定義的后面耐齐。 參數(shù)變量是默認(rèn)聲明的浪秘,所以不能...
    MrZhou_b216閱讀 179評(píng)論 0 0
  • 參數(shù)默認(rèn)值不是傳值的蒋情,而是每次都重新計(jì)算默認(rèn)值表達(dá)式的值。也就是說(shuō)耸携,參數(shù)默認(rèn)值是惰性求值的棵癣。 使用參數(shù)默認(rèn)值時(shí),函...
    ROBIN2015閱讀 317評(píng)論 0 0
  • 1 函數(shù)默認(rèn)值 1 惰性解析:參數(shù)默認(rèn)值不傳值夺衍,每次執(zhí)行函數(shù)的時(shí)候重新計(jì)算默認(rèn)值表達(dá)式的值 2 解構(gòu)賦值和參數(shù)...
    澳毅奧閱讀 129評(píng)論 0 0
  • 7.1函數(shù)參數(shù)的默認(rèn)值 7.1.1基本用法: 在es6之前浙巫,不能直接為函數(shù)的參數(shù)指定默認(rèn)值,只能采用變通的方法刷后。e...
    曼珠沙華_521b閱讀 186評(píng)論 0 0
  • 函數(shù)參數(shù)的默認(rèn)值 基本用法 ES6之前的畴,不能直接為函數(shù)的參數(shù)指定默認(rèn)值,只能采用變通的方法尝胆。 上面代碼檢查函數(shù)lo...
    oWSQo閱讀 243評(píng)論 0 0