第七章 函數(shù)表達(dá)式

第七章 函數(shù)表達(dá)式

問答

1. 函數(shù)聲明的語法是?

function test() {
  // ...
}

2. 函數(shù)表達(dá)式(匿名函數(shù))的語法是?

var test = function() {
  // ...
};

3. 以下遞歸語句是否報(bào)錯, 報(bào)錯原因是? 如何改進(jìn)?

function factorial (num) {
  if (num <= 1) {
    return 1
  } else {
    return num * factorial(num - 1)
  }
}

var anotherFactorial = factorial
factorial = null
anotherFactorial(4)

錯誤: Uncaught TypeError: factorial is not a function

原因: 函數(shù)factorial內(nèi)部的factorial指向null, 因此報(bào)錯.

方法1: arguments.callee, 它指向當(dāng)前正在執(zhí)行的函數(shù)指針. 但是嚴(yán)格模式不允許使用.

function factorial (num) {
  if (num <= 1) {
    return 1
  } else {
    return num * arguments.callee(num - 1)
  }

方法2: 函數(shù)表達(dá)式

var factorial = function f (num) {
  if (num <= 1) {
    return 1
  } else {
    return num * f(num - 1)
  }
}

4. 閉包的概念?

有權(quán)訪問另一個函數(shù)作用域中的變量的函數(shù)(或其他). 只要不被垃圾回收機(jī)制回收即可, 不一定需要返回函數(shù), 方式有:

  • 在一個函數(shù)中返回另一個函數(shù), 返回的函數(shù)中包含上層函數(shù)的活動對象和全局對象(層層向外, 不止兩層)
  • 在函數(shù)中將內(nèi)部狀態(tài)保存在外部變量中.
var test = (function () {
  var test = 123
  function fn () {
    return test
  }
  TEST = {
    test: test,
    fn: fn
  }
})()
console.log(TEST.fn()) // 123 , 注意: window.TEST === TEST
console.log(TEST) // {test:123, fn:f}

5. 在閉包中, 函數(shù)被調(diào)用的時候都發(fā)生了什么?

function createComparisonFunction (propertyName) {
  return function (object1, object2) {
    var value1 = object1[propertyName]
    var value2 = object2[propertyName]
    if (value1 < value2) {
      return -1
    } else if (value1 > value2) {
      return 1
    } else {
      return 0
    }
  }
}

// 創(chuàng)建函數(shù)
var compareNames = createComparisonFunction('name')
// 調(diào)用函數(shù)
var result = compareNames({ name: 'Nicholas' }, { name: 'Greg' })
// 解除對匿名函數(shù)的引用,釋放內(nèi)存
compareNames = null
創(chuàng)建createComparisonFunction函數(shù)
  1. 當(dāng)創(chuàng)建createComparisonFunction函數(shù)時, 會創(chuàng)建一個預(yù)先包含全局變量對象的作用域鏈, 這個作用域鏈被保存在當(dāng)前函數(shù)內(nèi)部的[[Scopes]]屬性中.
執(zhí)行createComparisonFunction函數(shù)
  1. 當(dāng)執(zhí)行createComparisonFunction函數(shù)時, 會創(chuàng)建一個執(zhí)行環(huán)境(execution context), 通過復(fù)制函數(shù)的[[Scopes]]屬性中的對象構(gòu)建起執(zhí)行環(huán)境的作用域鏈.

  2. 使用arguments和其他 形參/變量/函數(shù)聲明 初始化函數(shù)的 活動對象(activation object), 即另一種局部變量對象, 并被推入執(zhí)行環(huán)境作用域鏈的頂端. 這里需要補(bǔ)充變量提升及優(yōu)先級的說明.

  3. 此時, createComparisonFunction函數(shù)的執(zhí)行環(huán)境中的作用域鏈包含多個變量對象:

    • 0: 本地活動對象
    • 1: 引用的外層函數(shù)變量對象
    • n-1: ...
    • n: 全局變量對象.
  4. 顯然, 作用域鏈的本質(zhì)是一個指向變量對象的指針列表, 它只包含引用但不實(shí)際包含變量對象.

  5. 當(dāng)在函數(shù)中訪問一個變量時, 就會從作用域鏈中搜索具有相應(yīng)名字的變量(變量標(biāo)識符匹配過程). 這里可以補(bǔ)充優(yōu)化機(jī)制.

  6. 當(dāng)createComparisonFunction函數(shù)執(zhí)行完畢時, 其執(zhí)行環(huán)境的作用域鏈會被銷毀.

創(chuàng)建閉包
  1. 當(dāng)匿名函數(shù)從createComparisonFunction函數(shù)中返回后, 它的作用域鏈被初始化為包含createComparisonFunction函數(shù)的活動對象和全局變量對象.
執(zhí)行閉包
  1. 因此, 即使createComparisonFunction函數(shù)執(zhí)行完畢, 但是它的活動對象仍然會留在內(nèi)存中, 直到匿名函數(shù)主動銷毀, createComparisonFunction()的活動對象才會被銷毀. 這里需要補(bǔ)充JS垃圾回收及標(biāo)記清除機(jī)制.

注意:

  1. 閉包保存的是整個變量對象, 而不是某個特殊的變量.
  2. 只要沒有形成閉包, 當(dāng)函數(shù)執(zhí)行完畢, 就可以立即銷毀其作用域鏈和活動對象(變量對象).
  3. 如果形成閉包, 作用域鏈也會被銷毀, 但是活動對象及變量對象不會銷毀.
  4. 作用域鏈決定哪些數(shù)據(jù)能被函數(shù)訪問

6. 下面函數(shù)返回的是什么, 為什么?

var name = "The Window";
var object = {
  name: "My Object",
  getNameFunc: function() {
    return function() {
    // this只有執(zhí)行時在確定指向誰, 當(dāng)前this指定window
    // 活動對象中只有window
      return this.name;    
     };
  }
};
console.log(object.getNameFunc()()); // The Window

匿名函數(shù)的執(zhí)行環(huán)境具有全局性, 因此其this對象通常指向window(這里可以使用call/apply主動改變this).

this的概念: 在函數(shù)運(yùn)行時牍汹,基于調(diào)用位置的條件自動生成的內(nèi)部對象,可以理解為動態(tài)綁定對象到this上瓦胎。

每個函數(shù)在被調(diào)用時都會自動取得兩個特殊的變量: thisarguments. 內(nèi)部函數(shù)在搜索這兩個變量時, 只會搜索到其活動變量為止, 因此最后一個函數(shù)執(zhí)行時, 外層function的活動對象只有window, this為window, 即, this === window.

因此, 函數(shù)執(zhí)行時才能確定this, 且this指向調(diào)用函數(shù)最近的一個對象.

7. IIFE能模仿塊級作用域的原因?

JavaScript是函數(shù)級作用域, 在立即執(zhí)行函數(shù)內(nèi)定義的變量是局部變量, 一般情況下, 使用完畢后會自動銷毀.

8. 關(guān)于作用域鏈優(yōu)化部分的理解?

  • 緩存深層作用域鏈上的變量

變量使用前都會在作用域鏈中查找, 因此將常用的跨作用域變量緩存為局部變量能減少變量查找時間

  • 避免使用with

with能動態(tài)改變作用域鏈, 將指定的對象壓入作用域鏈頂端, 造成原來局部變量對象轉(zhuǎn)為第二位, 影響查找效率.

  • catch內(nèi)部使用簡化代碼

當(dāng)try代碼中發(fā)生錯誤時, 執(zhí)行過程會自動跳轉(zhuǎn)到catch中, 然后把異常對象推入一個變量對象并置于作用域的首位, 建議catch中不要放復(fù)雜的語句

  • 盡量不使用eval()

    • 非嚴(yán)格模式下, eval中的語句只有在執(zhí)行時才知道是否有內(nèi)部變量污染外部環(huán)境;
    • 嚴(yán)格模式為eval中的變量為局部作用域
    • 此外, js引擎無法對動態(tài)作用域進(jìn)行優(yōu)化, 只能按照作用域鏈查找的傳統(tǒng)模式進(jìn)行執(zhí)行.
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末车荔,一起剝皮案震驚了整個濱河市琳彩,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌谷徙,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,372評論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異蔗候,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)埂软,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,368評論 3 392
  • 文/潘曉璐 我一進(jìn)店門锈遥,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事所灸±龌蹋” “怎么了?”我有些...
    開封第一講書人閱讀 162,415評論 0 353
  • 文/不壞的土叔 我叫張陵爬立,是天一觀的道長钾唬。 經(jīng)常有香客問我,道長侠驯,這世上最難降的妖魔是什么知纷? 我笑而不...
    開封第一講書人閱讀 58,157評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮陵霉,結(jié)果婚禮上琅轧,老公的妹妹穿的比我還像新娘。我一直安慰自己踊挠,他們只是感情好乍桂,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,171評論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著效床,像睡著了一般睹酌。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上剩檀,一...
    開封第一講書人閱讀 51,125評論 1 297
  • 那天憋沿,我揣著相機(jī)與錄音,去河邊找鬼沪猴。 笑死辐啄,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的运嗜。 我是一名探鬼主播壶辜,決...
    沈念sama閱讀 40,028評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼担租,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了奋救?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,887評論 0 274
  • 序言:老撾萬榮一對情侶失蹤尝艘,失蹤者是張志新(化名)和其女友劉穎演侯,沒想到半個月后利耍,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體蚌本,經(jīng)...
    沈念sama閱讀 45,310評論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡盔粹,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,533評論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了程癌。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片舷嗡。...
    茶點(diǎn)故事閱讀 39,690評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖嵌莉,靈堂內(nèi)的尸體忽然破棺而出进萄,到底是詐尸還是另有隱情,我是刑警寧澤锐峭,帶...
    沈念sama閱讀 35,411評論 5 343
  • 正文 年R本政府宣布中鼠,位于F島的核電站,受9級特大地震影響沿癞,放射性物質(zhì)發(fā)生泄漏援雇。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,004評論 3 325
  • 文/蒙蒙 一椎扬、第九天 我趴在偏房一處隱蔽的房頂上張望惫搏。 院中可真熱鬧,春花似錦蚕涤、人聲如沸筐赔。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽茴丰。三九已至,卻和暖如春天吓,著一層夾襖步出監(jiān)牢的瞬間贿肩,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,812評論 1 268
  • 我被黑心中介騙來泰國打工失仁, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留尸曼,地道東北人。 一個月前我還...
    沈念sama閱讀 47,693評論 2 368
  • 正文 我出身青樓萄焦,卻偏偏與公主長得像,于是被迫代替她去往敵國和親冤竹。 傳聞我的和親對象是個殘疾皇子拂封,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,577評論 2 353

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

  • 1.定義函數(shù)的方式: ①函數(shù)聲明(其重要特征是函數(shù)聲明提升,可以把函數(shù)聲明放在調(diào)用它的語句后面): functio...
    張果果閱讀 222評論 0 0
  • 定義函數(shù)的方式有兩種: 函數(shù)聲明重要特征就是函數(shù)聲明提升鹦蠕,意思是在執(zhí)行代碼之前會先讀取函數(shù)聲明冒签。這就意味著可以把函...
    dudu_du閱讀 232評論 0 0
  • 還記得前年看了《黃飛鴻之英雄有夢》后,久久地迷戀于五月天的那首《將軍令》钟病,簡直好聽的無法自拔萧恕。每聽一遍都能想到j(luò)a...
    召小南閱讀 968評論 0 6
  • 我坐在回家的車上票唆,經(jīng)過了八天的軍訓(xùn)洗禮與幾天的混吃等死朴读,我經(jīng)歷我夢寐以求的大學(xué),卻沒有找到我最初的感覺走趋,就像是荒廢...
    舊城咯閱讀 153評論 0 0
  • 傷了翅膀的鳥兒 音符寫夢 2014-7-18 9:53 湛藍(lán)的天空中 偶爾會有幾朵白云飄過 三三兩兩的鳥兒們 在嘰...
    如伊老師閱讀 247評論 0 1