JavaScript筆記贺嫂;函數(shù)的基本特性

猶記得第一次寫(xiě)JS的時(shí)候,還是從定義一個(gè)函數(shù)開(kāi)始第喳。

function first() {
     ....
}

那個(gè)時(shí)候只是把函數(shù)作為一個(gè)組織代碼的方式而已,過(guò)后不久,寫(xiě)網(wǎng)頁(yè)應(yīng)用寞射,jquery占據(jù)了我的絕大部分時(shí)間。寫(xiě)的一手很溜的JQ選擇器引矩,是我自認(rèn)為牛逼的開(kāi)始侵浸。浮華褪盡,裝逼再多掏觉,也慢慢明白需要返璞歸真。因此织盼,近來(lái)開(kāi)始研習(xí)js的基本功酱塔,理解它一些不可思議的魔法沥邻。偶得心得一二羊娃。

0x00 引言

函數(shù)是JS的第一型對(duì)象,對(duì)象在JS中擁有以下特性:

可以通過(guò)字面量創(chuàng)建

賦值給變量邮利,數(shù)組和其他對(duì)象的屬性

作為參數(shù)傳遞函數(shù)

作為函數(shù)的返回值

擁有動(dòng)態(tài)創(chuàng)建并賦值的屬性

也就是說(shuō),function f(){};其實(shí)是建立了一個(gè)f的變量缅糟,指向一個(gè)函數(shù)實(shí)體祷愉。

0x01 屬性

函數(shù)也是有屬性的,這一點(diǎn)不要驚訝二鳄。正如上面那個(gè)例子提到的。function f(){};,f函數(shù)可以通過(guò)一個(gè)叫name屬性髓窜,查看函數(shù)的名字:

> function f(){};
<·function f(){}
>f.name
<·"f"

而其中還有一個(gè)特別注明的屬性--prototype欺殿。在很多JS的面向?qū)ο蟮慕虒W(xué)上面都會(huì)提到這個(gè)給函數(shù)動(dòng)態(tài)增加屬性和方法的函數(shù)屬性。那么這個(gè)屬性是什么呢程拭?

其實(shí)只要簡(jiǎn)單輸出的一下棍潘,你就明白:

> f.prototype
<· object{}

這個(gè)屬性代表的是一個(gè)對(duì)象,而如果你繼續(xù)探究的話亦歉,就要說(shuō)到另一個(gè)屬性constructor,這個(gè)屬性肴楷,稍微面向?qū)ο缶幊袒A(chǔ)的人,都能明白赛蔫,這個(gè)屬性代表的是構(gòu)造器。這個(gè)屬性是函數(shù)和對(duì)象都有的鞭盟,表示這個(gè)函數(shù)或者對(duì)象的構(gòu)造器是那一個(gè)瑰剃。

如果我們查看prototype的構(gòu)造器的話,你會(huì)發(fā)現(xiàn):

> f.prototype.constructor
<· function f(){}

其實(shí)就是函數(shù)f,這樣你就明白為什么歇竟,prototype屬性為什么能夠給函數(shù)增加屬性和方法了抵恋,應(yīng)為這東西就是該函數(shù)本身作為構(gòu)造器構(gòu)造的一個(gè)對(duì)象。

prototypeconstructor談到構(gòu)造器的時(shí)候盅安,再深入說(shuō)明世囊。需要明白的是,函數(shù)也是有屬性的株憾。

函數(shù)還有一個(gè)特殊的屬性arguments,透過(guò)字面意思你也能知道墙歪,這個(gè)屬性指向的是調(diào)用這個(gè)函數(shù)的參數(shù)列表贝奇。這是一個(gè)特殊的對(duì)象。它可以被當(dāng)作數(shù)組遍歷使用,但是他不是一個(gè)數(shù)組髓帽,所以不能使用數(shù)組的方法來(lái)操作它。

正是應(yīng)為這個(gè)屬性的存在衡查,所以即使函數(shù)調(diào)用函數(shù)的參數(shù)對(duì)象是不完整的也依舊可以調(diào)用這個(gè)函數(shù)必盖。而額外的參數(shù),也可以通過(guò)arguments來(lái)調(diào)用使用歌粥。

0x02 上下文

上下文(context)是很多語(yǔ)言都有的一個(gè)概念失驶。在Java中有著十分嚴(yán)格的規(guī)定和約束,但是JS中卻是靈活多變。在函數(shù)的內(nèi)部棉圈,上下文用this表示眷蜓。在Java等面向?qū)ο笳Z(yǔ)言中,this表示的是調(diào)用這個(gè)方法或者屬性的對(duì)象吁系。

例如:obj.foo = function(){return this;};這樣的方式很好理解,調(diào)用obj.foo()方法氏捞,返回的是對(duì)象obj冒版。

但如果我們直接生命一個(gè)函數(shù),沒(méi)有把它賦予給任何一個(gè)對(duì)象呢捆等?

> function f() {return this;};
> f();
<· window{...}

這樣很好理解续室,當(dāng)沒(méi)有給一個(gè)函數(shù)指定上下文的時(shí)候,它的上下文是window挺狰。當(dāng)然丰泊,這是在瀏覽器中,其他環(huán)境中我還沒(méi)有研究瞳购。但遠(yuǎn)離應(yīng)該是相同的,即沒(méi)有賦予上下文環(huán)境的時(shí)候年堆,賦予的最頂級(jí)的上下文環(huán)境盏浇。

將一個(gè)函數(shù)賦予給一個(gè)對(duì)象作為它的方法,是一種改變函數(shù)上下文的方式绢掰。如果我們想要?jiǎng)討B(tài)的改變函數(shù)的上下文呢。就比如谊却,一段代碼,我們要等運(yùn)行到一個(gè)結(jié)果后捕透,才能指定這個(gè)函數(shù)的上下文來(lái)調(diào)用碴萧。這就是JS中常用的回調(diào)機(jī)制,而這個(gè)時(shí)候就要用到的函數(shù)的兩個(gè)特殊的方法call()apply()破喻。

這兩個(gè)方法的作用曹质,都是為一個(gè)函數(shù)指定上下文。不同的是羽德,調(diào)用的參數(shù)不同。

  • call:

    call方法第一個(gè)參數(shù)接收的是要指定給函數(shù)的上下文章蚣,之后的參數(shù)依次賦予函數(shù)對(duì)應(yīng)的參數(shù)姨夹。

    f.call(obj, arg1, arg2, arg3)

  • apply:

    apply方法第一個(gè)參數(shù)也是接收的指定給函數(shù)的上下文,第二個(gè)參數(shù)接收的是一個(gè)數(shù)組或者arguments峭沦。將數(shù)組的元素依次匹配到函數(shù)上够颠,或者將arguments傳遞給函數(shù)調(diào)用榄鉴。

    f.apply(obj, [arg1, arg2, arg3])f.apply(obj, arguments)

0x03 閉包

閉包這種特性,可以理解為作用域剃诅。當(dāng)然驶忌,這和Java等語(yǔ)言中的作用域是不一樣笑跛。JS中的“作用域”更加具有函數(shù)式語(yǔ)言的特性聊品。

舉個(gè)栗子:

if(flag) {
    var a = 3;
} else {
    var a = 4;
}

console.log(a);

這樣的代碼中,a是可以被調(diào)用的翻屈。而在Java中這是會(huì)報(bào)錯(cuò)伸眶。這就是說(shuō)明,JS中的“作用域”其實(shí)不是和Java中那樣是以代碼塊為原子的厘贼,而是以函數(shù)為原子的。這就被稱之為閉包毁欣。

閉包的原則赁遗,很通俗的一條語(yǔ)言可以概括你的是我的,我的還是我的哭尝。

即一個(gè)函數(shù)的中的資源剖煌,不可以被外部訪問(wèn),但其內(nèi)部可以訪問(wèn)耕姊。如果下面一個(gè)函數(shù)的嵌套:

    function a() {
        function b() {
            function c() {
                ...
            }
        }
    }

a外面不能調(diào)用bc,a中可以調(diào)用b,但不能調(diào)用c茉兰。依次類(lèi)推,內(nèi)部可以訪問(wèn)外部规脸,外部不能訪問(wèn)內(nèi)部。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末闹丐,一起剝皮案震驚了整個(gè)濱河市卿拴,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌堕花,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,546評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件如贷,死亡現(xiàn)場(chǎng)離奇詭異到踏,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)楣富,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,224評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén)纹蝴,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)踪少,“玉大人,你說(shuō)我怎么就攤上這事援奢。” “怎么了切黔?”我有些...
    開(kāi)封第一講書(shū)人閱讀 164,911評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵具篇,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我诗芜,道長(zhǎng)埃疫,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,737評(píng)論 1 294
  • 正文 為了忘掉前任脐湾,我火速辦了婚禮叙淌,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘闻鉴。我一直安慰自己茂洒,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,753評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布渠羞。 她就那樣靜靜地躺著智哀,像睡著了一般。 火紅的嫁衣襯著肌膚如雪屯吊。 梳的紋絲不亂的頭發(fā)上摹菠,一...
    開(kāi)封第一講書(shū)人閱讀 51,598評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音蔽介,去河邊找鬼煮寡。 笑死,一個(gè)胖子當(dāng)著我的面吹牛洲押,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播体箕,決...
    沈念sama閱讀 40,338評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼累铅,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼站叼!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起尽楔,我...
    開(kāi)封第一講書(shū)人閱讀 39,249評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎玛荞,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體婴梧,經(jīng)...
    沈念sama閱讀 45,696評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡客蹋,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,888評(píng)論 3 336
  • 正文 我和宋清朗相戀三年讶坯,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片闽巩。...
    茶點(diǎn)故事閱讀 40,013評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡涎跨,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出隅很,到底是詐尸還是另有隱情叔营,我是刑警寧澤,帶...
    沈念sama閱讀 35,731評(píng)論 5 346
  • 正文 年R本政府宣布畜挥,位于F島的核電站婴谱,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏谭羔。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,348評(píng)論 3 330
  • 文/蒙蒙 一客叉、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧卵慰,春花似錦向族、人聲如沸棠绘。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,929評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)让虐。三九已至紊撕,卻和暖如春赡突,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背浪南。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,048評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工漱受, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人絮记。 一個(gè)月前我還...
    沈念sama閱讀 48,203評(píng)論 3 370
  • 正文 我出身青樓虐先,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親憔四。 傳聞我的和親對(duì)象是個(gè)殘疾皇子般眉,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,960評(píng)論 2 355

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