js引用類型之Function類型

一省撑、函數(shù)的定義

定義函數(shù)有三種方式:函數(shù)聲明充石、函數(shù)表達(dá)式颈畸、Function構(gòu)造函數(shù)(不推薦)

函數(shù)聲明比如:

function sum(num1,num2){

return num1 + num2;

}


函數(shù)表達(dá)式咐旧,其實(shí)就是變量聲明的一種蝶涩,這種定義方式得到的函數(shù)也叫匿名函數(shù)(拉姆達(dá)函數(shù))理朋,因?yàn)閒unction關(guān)鍵字后面沒有函數(shù)名字,只是把這個函數(shù)體賦值給一個變量绿聘。這種方式定義函數(shù)也沒有必要使用函數(shù)名---通過變量名就可以引用函數(shù)嗽上。另外還要注意,此時函數(shù)末尾有一個分號斜友,就像聲明其他變量一樣需要一個分號作為結(jié)尾炸裆。比如:

var sum = function (num1,num2){

return num1 + num2;

};

Function構(gòu)造函數(shù)可以接收任意數(shù)量的參數(shù),但最后一個參數(shù)始終都被看成函數(shù)體鲜屏,而前面的參數(shù)枚舉出了新函數(shù)的參數(shù)烹看。比如:

var sum = new Function("num1","num2","return num1 + num2");? ? ? ? //不推薦

從技術(shù)上講,這是一個函數(shù)表達(dá)式洛史,但是這種語法會導(dǎo)致解析兩次代碼(第一次是解析常規(guī)的ES代碼惯殊,第二次是解析傳入構(gòu)造函數(shù)中的字符串),從而影響性能也殖。不過土思,這種語法對于理解“函數(shù)是對象,函數(shù)名是指針”的概念倒是非常直觀的忆嗜。

二己儒、函數(shù)的內(nèi)部屬性

總得來說,函數(shù)的內(nèi)部屬性有三個:arguments(ES3)? this(ES3)? caller(ES5)捆毫。

(一)arguments

小知識:ES函數(shù)的參數(shù)與大多數(shù)其他語言中函數(shù)的參數(shù)有些不同闪湾,ES函數(shù)不介意傳遞的參數(shù)個數(shù)滿足符合定義函數(shù)時要求的個數(shù)。命名的參數(shù)只提供便利绩卤,并不是必需的途样。也就是說,即使你定義函數(shù)時濒憋,只接收兩個參數(shù)何暇,在調(diào)用這個函數(shù)時,可以傳入一個凛驮,兩個裆站,三個甚至不傳遞參數(shù),這是因?yàn)椋珽S函數(shù)中的參數(shù)在內(nèi)部是用一個數(shù)組來表示的遏插,函數(shù)接收到的只是這個數(shù)組捂贿,并不關(guān)心數(shù)組中包含哪些參數(shù)(如果有參數(shù)的話)纠修。

1胳嘲、參數(shù)個數(shù)任意(沒有傳遞值的命名參數(shù)被自動賦予undefined)

arguments是一個類數(shù)組對象(因?yàn)榭梢允褂梅嚼ㄌ栒Z法訪問它的每一個元素,即第一個元素arguments[0]扣草,第二個元素arguments[1]等了牛,但是,它只是與數(shù)組類似辰妙,并不是一個Array實(shí)例)鹰祸,它的作用是存儲傳入函數(shù)的所有參數(shù)。

function a(){

alert(arguments.length);

}

a ( "string" , 2 );? ? ? ? ? ? ? //2

a (2 );? ? ? ? ? ? ? ? ? ? ? ? ? ? //1

a ( );? ? ? ? ? ? ? ? ? ? ? ? ? ? ? //0

我們可以根據(jù)參數(shù)個數(shù)不同來實(shí)現(xiàn)不同的功能:

function a(){

if ( arguments.length == 1 ){

alert(arguments[0] + 10 );

}

else if ( arguments.length == 2 ){

alert(arguments[0] + arguments[1] );

}

}

a(10);? ? ? ? ? ? //20

a( 30 , 20);? ? //50

2密浑、arguments可以和命名參數(shù)一起使用

function a( num1 ,num2 ){

if ( arguments.length == 1 ){

alert( num1 + 10 );

}

else if ( arguments.length == 2 ){

alert(arguments[0] + num2 );

}

}

上述代碼中蛙婴,num1和arguments[0]的值相同,所以可以互換著使用尔破。

記住一點(diǎn)街图,ES中所有函數(shù)的參數(shù)都是按值傳遞的,也就是說懒构,把函數(shù)外部的值復(fù)制給函數(shù)內(nèi)部的參數(shù)餐济,就和把值從一個變量復(fù)制到另一個變量一樣〉ň纾基本類型值的傳遞如同基本類型變量的賦值一樣(被傳遞的值會被復(fù)制給一個局部變量絮姆,即命名參數(shù),也可以說是arguments對象中的一個元素)秩霍,引用類型值的傳遞就如同引用類型變量的賦值一樣(把這個值在內(nèi)存中的地址復(fù)制給一個局部變量篙悯,因此這個局部變量的變化會反映在函數(shù)的外部P71)。

3铃绒、arguments.callee

callee是arguments的一個很重要的屬性鸽照,該屬性是一個指針,指向擁有這個arguments對象的函數(shù)匿垄。

function factorial ( num ){

if( num <=1){

return 1;

}else{

return num * factorial( num -1 );

}

}

var trueFactorial = factorial;

factorial = function (){

? ? return 0;

};

alert(trueFactorial (5));? ? ? //0

alert(factorial (5));? ? ? ? ? ? //0

這是一個階乘函數(shù)移宅,但是這個函數(shù)的執(zhí)行與函數(shù)名factorial緊緊耦合,當(dāng)函數(shù)名修改成trueFactorial 之后椿疗,調(diào)用trueFactorial ()函數(shù)就會返回0漏峰。是因?yàn)椋兞縯rueFactorial 獲得了factorial的值届榄,實(shí)際上是在另一個位置上保存了一個函數(shù)的指針浅乔。然后又將一個簡單的返回0的函數(shù)賦值給factorial變量。? 為了消除這種耦合,我們可以使用arguments.callee靖苇。如下席噩,這樣便可以解除函數(shù)體內(nèi)的代碼與函數(shù)名的耦合狀態(tài),trueFactorial() 可以正常的計(jì)算階乘贤壁;至于factorial() 現(xiàn)在只是個返回0 的函數(shù)悼枢。

function factorial ( num ){

if( num <=1){

return 1;

}else{

return num *arguments.callee( num -1 );

}

}

var trueFactorial = factorial;

factorial = function (){

return 0;

};

alert(trueFactorial (5));? ? ? //120

alert(factorial (5));? ? ? ? ? ? ? //0

4、arguments.caller

見(三)caller()介紹脾拆。

為了實(shí)現(xiàn)更松散的耦合馒索,ES5定義的arguments.callee.caller,定義這個屬性是為了區(qū)分arguments.caller和函數(shù)的caller的區(qū)別名船,arguments.caller嚴(yán)格模式下會報錯绰上,非嚴(yán)格模式下等于undefined。

(二)this

this的行為與Java和C#中的this類似渠驼,this引用的是函數(shù)執(zhí)行的環(huán)境對象蜈块。

(三)caller

這個是ES5新定義的屬性,這個屬性保存調(diào)用當(dāng)前函數(shù)的函數(shù)的引用

因?yàn)閛uter()調(diào)用了inner()迷扇,所以inner.caller指向outer()百揭。

嚴(yán)格模式下,不能為函數(shù)caller屬性賦值谋梭。

三信峻、函數(shù)的屬性和方法

函數(shù)有兩個屬性:length prototype

函數(shù)有三個方法:call()? apply()? bind()--ES5

(一)屬性

1、length

length屬性表示函數(shù)希望接收的命名參數(shù)的個數(shù)

function a(num){

? alert(num);

}

function b(num1,num2){

? return num1+num2;

}

function c(){

? alert("num");

}

alert(a.length);? ? //1

alert(b.length);? ? //2

alert(c.length);? ? //0

2瓮床、prototype

(二)方法

1盹舞、call()和apply()

每個函數(shù)自身都有兩個方法:apply()和call()。這兩個方法都是在特定的作用域內(nèi)調(diào)用函數(shù)隘庄,也就是修改函數(shù)體內(nèi)this對象的指向踢步。他倆的區(qū)別是接收參數(shù)的方式略有不同。(先講如何使用)

apply()接收兩個參數(shù)丑掺,一個是在其中運(yùn)行函數(shù)的作用域获印,另一個是參數(shù)數(shù)組;

call()一樣地接收兩個參數(shù)街州,一個是在其中運(yùn)行函數(shù)的作用域兼丰,另一個是枚舉出所有的參數(shù);

function a(num1,num2){

? return num1+num2;

}

function callA1(num1,num2){

? return a.apply(this,arguments);? ? //arguments是一個類數(shù)組對象

}

function callA2(num1,num2){

? return a.apply(this,[num1,num2]);

}

function callA3(num1,num2){

? return a.call(this,num1,num2);

}

alert(callA1(10,10));? ? //20

alert(callA2(10,10));? ? //20

alert(callA3(10,10));? ? //20

(再來說一下他們的強(qiáng)大之處)

前文提到過唆缴,他們的作用是修改函數(shù)體內(nèi)的this指向鳍征,也就是他們可以動態(tài)擴(kuò)展函數(shù)運(yùn)行的作用域,這也是this四種綁定方式之顯性綁定原則面徽。

使用call()和apply()來擴(kuò)充作用域的好處是對象不需要與方法有任何的耦合關(guān)系艳丛。

2匣掸、bind()

當(dāng)在函數(shù)f()上調(diào)用bind()方法并傳入一個對象o作為參數(shù),這個方法將返回一個新函數(shù)氮双。(以函數(shù)調(diào)用的方式)調(diào)用新的函數(shù)將會把原始的函數(shù)f()當(dāng)做o的方法來調(diào)用碰酝。

function f ( y ) {

return this.x+y;

}

var o={

x:1;

}

var g = f.bind(o);

g(2)? ? //3

bind()會創(chuàng)建一個實(shí)例,其this值會被綁定到bind()函數(shù)的值戴差,this的四種綁定里面這個叫做顯示綁定之硬綁定

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末送爸,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子造挽,更是在濱河造成了極大的恐慌碱璃,老刑警劉巖弄痹,帶你破解...
    沈念sama閱讀 219,589評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件饭入,死亡現(xiàn)場離奇詭異,居然都是意外死亡肛真,警方通過查閱死者的電腦和手機(jī)谐丢,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,615評論 3 396
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來蚓让,“玉大人乾忱,你說我怎么就攤上這事±” “怎么了窄瘟?”我有些...
    開封第一講書人閱讀 165,933評論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長趟卸。 經(jīng)常有香客問我蹄葱,道長,這世上最難降的妖魔是什么锄列? 我笑而不...
    開封第一講書人閱讀 58,976評論 1 295
  • 正文 為了忘掉前任图云,我火速辦了婚禮,結(jié)果婚禮上邻邮,老公的妹妹穿的比我還像新娘竣况。我一直安慰自己,他們只是感情好筒严,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,999評論 6 393
  • 文/花漫 我一把揭開白布丹泉。 她就那樣靜靜地躺著,像睡著了一般鸭蛙。 火紅的嫁衣襯著肌膚如雪摹恨。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,775評論 1 307
  • 那天规惰,我揣著相機(jī)與錄音睬塌,去河邊找鬼。 笑死,一個胖子當(dāng)著我的面吹牛揩晴,可吹牛的內(nèi)容都是我干的勋陪。 我是一名探鬼主播,決...
    沈念sama閱讀 40,474評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼硫兰,長吁一口氣:“原來是場噩夢啊……” “哼诅愚!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起劫映,我...
    開封第一講書人閱讀 39,359評論 0 276
  • 序言:老撾萬榮一對情侶失蹤违孝,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后泳赋,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體雌桑,經(jīng)...
    沈念sama閱讀 45,854評論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,007評論 3 338
  • 正文 我和宋清朗相戀三年祖今,在試婚紗的時候發(fā)現(xiàn)自己被綠了校坑。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,146評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡千诬,死狀恐怖耍目,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情徐绑,我是刑警寧澤邪驮,帶...
    沈念sama閱讀 35,826評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站傲茄,受9級特大地震影響毅访,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜烫幕,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,484評論 3 331
  • 文/蒙蒙 一俺抽、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧较曼,春花似錦磷斧、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,029評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至萍歉,卻和暖如春侣颂,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背枪孩。 一陣腳步聲響...
    開封第一講書人閱讀 33,153評論 1 272
  • 我被黑心中介騙來泰國打工憔晒, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留藻肄,地道東北人。 一個月前我還...
    沈念sama閱讀 48,420評論 3 373
  • 正文 我出身青樓拒担,卻偏偏與公主長得像嘹屯,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子从撼,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,107評論 2 356

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

  • Chapter 5 引用類型 Object類型 創(chuàng)建Object實(shí)例new Object()var person ...
    云之外閱讀 391評論 0 0
  • 本文檔內(nèi)容參考 《JavaScript 闖關(guān)記》之函數(shù) 函數(shù)是一段代碼州弟,它只定義一次,但可以被執(zhí)行或調(diào)用任意次低零。在...
    穿越人海遇見你閱讀 1,003評論 0 1
  • 第一章: JS簡介 從當(dāng)初簡單的語言婆翔,變成了現(xiàn)在能夠處理復(fù)雜計(jì)算和交互,擁有閉包掏婶、匿名函數(shù)啃奴, 甚至元編程等...
    LaBaby_閱讀 1,674評論 0 6
  • 之前寫過函數(shù)也屬于引用類型,與其他引用類型一樣也是具有屬性和方法气堕。由于函數(shù)是對象纺腊,繼承自object,因此函數(shù)名實(shí)...
    Miss____Du閱讀 5,770評論 4 17
  • 引用類型的值(對象)是引用類型的一個實(shí)例茎芭。在ECMAScript中,引用類型是一種數(shù)據(jù)結(jié)構(gòu)誓沸,用于將數(shù)據(jù)和功能組織在...
    AlexTamir閱讀 499評論 0 0