溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

JavaScript 中匿名函數(shù)有什么用

發(fā)布時(shí)間:2021-07-01 15:17:46 來(lái)源:億速云 閱讀:197 作者:Leah 欄目:大數(shù)據(jù)

這篇文章將為大家詳細(xì)講解有關(guān)JavaScript 中匿名函數(shù)有什么用,文章內(nèi)容質(zhì)量較高,因此小編分享給大家做個(gè)參考,希望大家閱讀完這篇文章后對(duì)相關(guān)知識(shí)有一定的了解。

本文源自知乎的一個(gè)提問(wèn):

JavaScript 中匿名函數(shù)有什么用  

同樣都是在運(yùn)行時(shí)才能確定函數(shù),為什么    b   是匿名函數(shù)?


這個(gè)看似簡(jiǎn)單的問(wèn)題,我在瀏覽器里搗鼓了一個(gè)多小時(shí)。而且好像發(fā)現(xiàn)了 FireFox/Chrome Devtools 的 2 個(gè)疑似 bug。
在 ES 規(guī)范中,有一個(gè)內(nèi)部函數(shù)    IsAnonymousFunctionDefinition()   用來(lái)判斷一個(gè)函數(shù)是否為匿名函數(shù),但是這個(gè)函數(shù)只在規(guī)范中使用,通過(guò) JS 代碼并不能調(diào)用,很多 JS 引擎會(huì)在內(nèi)部實(shí)現(xiàn)這個(gè)函數(shù)(非強(qiáng)制要求)。
當(dāng)我們談到匿名函數(shù)時(shí),其實(shí)有 2 種不同的含義:
  1. 函數(shù)沒(méi)有名字
  2. 函數(shù)的  name  屬性是 "anonymous"
由于函數(shù)的    name  是繼承自    Function.prototype.name  ,因此沒(méi)有名字的函數(shù)的    name  屬性是空字符    ""  。
在大部分調(diào)試工具中,沒(méi)有名字的函數(shù)會(huì)顯示為    <anonymous>  ,也就是我們經(jīng)常說(shuō)的匿名函數(shù)。
我們把題目中的代碼改寫一下:
  
    
  
  
  var a = () => () => { throw new Error('foo') }
不論是    a()()  ,還是    var b = a(); b()  ,在 Chrome 中執(zhí)行:

JavaScript 中匿名函數(shù)有什么用

可以清楚的看到,這個(gè)函數(shù)是匿名函數(shù)。(忽略最下面的匿名函數(shù),那個(gè)是    Global Scope  )
在 FireFox 的的調(diào)用棧都是:

JavaScript 中匿名函數(shù)有什么用

 這就太迷了。不論如何調(diào)用    b   函數(shù),    a   都不應(yīng)該出現(xiàn)在調(diào)用棧中,我覺(jué)得這應(yīng)該可以算是 FireFox 的一個(gè) bug 了。
如果使用    new Function   定義函數(shù),錯(cuò)誤棧里是沒(méi)有尖括號(hào)的。因?yàn)楦鶕?jù)規(guī)范,使用    Function   定義的函數(shù)是有名字的,名字就是    "anonymous"  。就好比一個(gè)人叫無(wú)名氏,并不是因?yàn)樗麤](méi)有名字,而是他姓無(wú),叫名氏。
在對(duì)于這個(gè)的處理上,F(xiàn)irefox 略勝一籌吧:
  
    
  
  
  var a = new Function('throw new Error("bar")')a()
FireFox 截圖:

JavaScript 中匿名函數(shù)有什么用

 我們?cè)倏匆幌?Chrome Devtools:

JavaScript 中匿名函數(shù)有什么用

 有點(diǎn)迷惑,可能是把引擎內(nèi)部的調(diào)用棧 dump 出來(lái)了吧。我覺(jué)得這個(gè)也可以被認(rèn)為是一個(gè) bug 了。
題主的疑惑是,為什么    var a = () => () => 1   的函數(shù)名是    a  ,而    var b = a()   就是匿名函數(shù)。
簡(jiǎn)單解釋就是,    var a = () => 1   包含了 2 個(gè)階段,箭頭函數(shù)定義和賦值操作。所有的箭頭函數(shù)都是匿名函數(shù),在箭頭函數(shù)的定義中,規(guī)范內(nèi)部的    hasName   屬性直接設(shè)置為了    false  。然后    IsAnonymousFunctionDefinition(expr)   判定此函數(shù)是匿名函數(shù):
  • If  IsFunctionDefinition  of  expr  is  false , return  false .
  • Let hasName be HasName of expr.
  • If hasName is true , return false .
  • Return  true .
當(dāng)賦值時(shí),會(huì)先判斷右值是否為匿名函數(shù)。如果是的話,重新設(shè)置函數(shù)名。
我們?cè)賮?lái)看看另一個(gè)語(yǔ)句:  var b = a()  。這個(gè)也包含了賦值操作,還有一個(gè)函數(shù)調(diào)用操作。
只有匿名函數(shù)(靜態(tài)語(yǔ)義)執(zhí)行賦值操作時(shí),才會(huì)為變量( rval  )重新設(shè)置 name   屬性,即函數(shù)名。這里的a()   只是一個(gè)函數(shù)調(diào)用,并不是函數(shù)定義, 所以不會(huì)重新設(shè)置函數(shù)名。
類似的:
  
    
  
  
  var a = (1, () => 'foo')a = [() => 1][0]var a = eval('()=>1')

關(guān)于JavaScript 中匿名函數(shù)有什么用就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,可以學(xué)到更多知識(shí)。如果覺(jué)得文章不錯(cuò),可以把它分享出去讓更多的人看到。

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI