JavaScript: 零基礎(chǔ)輕松學(xué)閉包(2)

注:本人發(fā)布的所有文章均為原創(chuàng)护赊,未經(jīng)作者許可惠遏,切勿轉(zhuǎn)載,謝謝骏啰。

本文面向初學(xué)者节吮,大神輕噴。

好了判耕,開始吧透绩。

上一節(jié) JavaScript: 零基礎(chǔ)輕松學(xué)閉包(1)中,我們對(duì)閉包的原理進(jìn)行了講解壁熄,這一節(jié)會(huì)說很多實(shí)戰(zhàn)性的東西了帚豪,可能會(huì)有點(diǎn)難度,你準(zhǔn)備好了嗎草丧?

1. 如何將私有數(shù)據(jù)暴露出去

還記得在上一節(jié)中志鞍,有這樣一個(gè)例子么?

var test = function(){
    var i = 10;
}

function test2(){
    alert(i);
}

test2();

函數(shù) test 和 test2 各自形成一個(gè)閉包方仿,兩個(gè)閉包之間無法訪問對(duì)方的私有數(shù)據(jù)。比如,在 test 中定義的變量仙蚜,在 test2 里面是無法直接訪問到的此洲。

那么問題來了, 當(dāng)然委粉,這邊和挖掘機(jī)沒關(guān)系呜师。這里的問題是,有沒有什么辦法讓 test2 可以訪問到其他閉包中的私有變量呢贾节?

辦法當(dāng)然是有的汁汗,最直接的想法就是,大不了我定義一個(gè)全局變量栗涂,在 test 中將私有數(shù)據(jù)賦給全局變量知牌,然后在 test2 里面就能訪問到了。

是的斤程,因?yàn)閮蓚€(gè)函數(shù)共同享有一個(gè)全局作用域角寸,所以這個(gè)辦法確實(shí)可行。我在很多項(xiàng)目里也的確看到很多人就是這么做的忿墅。

那么扁藕,有沒有一種更好的方法呢?要知道疚脐,全局作用域是一個(gè)比較敏感的地方亿柑,一不小心就會(huì)出現(xiàn)變量名重復(fù)的問題。順便說一句棍弄,在全局作用域中望薄,盡量不要使用諸如 temp , a , b , c 這一類的大眾化變量。

于是照卦,這就牽扯到返回值的相關(guān)知識(shí)了式矫,你在C語言的教材中肯定見慣了類似于這樣的代碼

int sum(int a,int b)
{
    return a + b;
}

int all = sum(3,5);

這是一個(gè)簡單的求和函數(shù),很多人慢慢地養(yǎng)成了這樣一個(gè)觀念役耕,就是函數(shù)的返回值就是一個(gè)字面值采转,要么是數(shù)字類型,要么是布爾類型瞬痘,或者是字符串故慈。

在很多強(qiáng)類型的語言,諸如 Java框全,C察绷,C++, 確實(shí)如此津辩。但是 return 在 JavaScript 中卻大有來頭拆撼。

在上一節(jié)已經(jīng)說明了容劳,js 的函數(shù)也是一種數(shù)據(jù)類型,你可以把函數(shù)看成是和int , float , double 一樣的東西闸度。

那么竭贩,既然int可以當(dāng)做函數(shù)的參數(shù)或者返回值,函數(shù)當(dāng)然也可以莺禁!

請(qǐng)看下面兩句話:

在js中

  • 如果函數(shù)被當(dāng)做參數(shù)傳進(jìn)去了留量,它就是所謂的回調(diào)函數(shù)。
  • 如果函數(shù)被當(dāng)做返回值return出去了哟冬,它就是把一個(gè)閉包return出去了楼熄。

這一章不講回調(diào)函數(shù),如果你不清楚啥叫回調(diào)函數(shù)浩峡,可以去看看這個(gè)小例子:
淺談js回調(diào)函數(shù)

還是上面的那個(gè)例子可岂,我們希望在 test2 中可以訪問到 test 里面的變量,可以這樣做:

var test = function(){
    var i = 10;
    /* 定義一個(gè)函數(shù)將變量i暴露出去  */
    var get = function(){
        return i ;
    }
    return get; //將獲得i的函數(shù)暴露出去
}

function test2(){
    
    var fn= test();//接收test暴露出來的函數(shù)
    alert(fn()); //獲得test中的私有數(shù)據(jù)
}

test2();
Paste_Image.png

test 函數(shù)中的 get 方法是一個(gè)內(nèi)部函數(shù)红符,它自己也形成了一個(gè)閉包青柄, test 是他的父級(jí)作用域,因此它可以獲取i的值预侯。

i 進(jìn)入 get 方法的閉包致开,被包了起來,然后最終被返回了出去萎馅。

而對(duì)于 test2 來說双戳,是可以訪問到 test函數(shù)的,因此可以調(diào)用并執(zhí)行 test 函數(shù)糜芳,從而獲取其返回值飒货。

你可能會(huì)說,我直接在test中把i給return出去就好了嘛峭竣,干嘛這么麻煩塘辅。

是的,言之有道理皆撩。

可是扣墩,如果我要訪問 test 中多個(gè)私有數(shù)據(jù)咋辦捏?

這下你可明白了吧扛吞!

現(xiàn)在呻惕,我們給出關(guān)于閉包的第二個(gè)注解:
(第一個(gè)注解在上一節(jié))

從應(yīng)用的角度來看,閉包可以將函數(shù)或者對(duì)象的私有數(shù)據(jù)暴露出去滥比,而不影響全局作用域亚脆。
Paste_Image.png

通過這張圖,是不是好理解一些了呢盲泛?我們這一節(jié)單說函數(shù)里的私有數(shù)據(jù)濒持。

2. 將私有數(shù)據(jù)包裝成json對(duì)象

剛才的例子說明键耕,在js中,return出去的可以是基本數(shù)據(jù)類型弥喉,也可以是函數(shù)類型郁竟。

其實(shí),JavaScript是一種基于對(duì)象的語言由境,也有對(duì)象的概念,所以蓖议,我們可以把你需要的東西包裹成一個(gè)對(duì)象返回出去虏杰!

上代碼:

var test = function(){
    var apple = '蘋果';
    var pear = '梨子';
    /* 定義一個(gè)函數(shù)將水果暴露出去  */
    var getFruit = {
        apple : apple ,
        pear : pear
    }
   
    return getFruit; //將獲得i的函數(shù)暴露出去
}

function test2(){
    
    var getFruit = test();//接收test暴露出來的函數(shù)
    
    console.log(getFruit);
}

test2();

像這樣用 { } 括起來的東西就是一個(gè)js對(duì)象,也就是所謂json勒虾。你可能經(jīng)常會(huì)聽到j(luò)son這個(gè)詞纺阔,覺得還挺高大上的。其實(shí)它就是一個(gè)用 { } 包起來的數(shù)據(jù)而已修然。

里面是鍵值對(duì)的形式笛钝,非常類似于Java里面的HashMap。

在這個(gè)例子中愕宋,我們可以直接把需要暴露的私有數(shù)據(jù)用一個(gè) { } 包起來玻靡,構(gòu)成一個(gè)json對(duì)象return出去就可以啦。

因?yàn)槭?js 對(duì)象中贝,alert 不能看到里面的具體內(nèi)容囤捻,所以我們使用 console.log() ,結(jié)果如下:

Paste_Image.png

展開后:

Paste_Image.png

這樣是不是也可以了邻寿?多出來的 proto 是原型鏈蝎土,以后會(huì)講到。

3. 我們來做一個(gè)紫金葫蘆

大家都還記得西游記里孫悟空用遮天的把戲騙來的紫金葫蘆嗎绣否,只要你拿著這個(gè)葫蘆誊涯,叫一聲別人的名字,如果答應(yīng)了蒜撮,別人就會(huì)被吸進(jìn)去暴构。

OK,這個(gè)紫金葫蘆里面不正如一個(gè)閉包嗎淀弹?

對(duì)不對(duì)嘛丹壕,所以,我們用閉包的知識(shí)來做一個(gè)好玩的東西吧薇溃。

<body>
    <div id='box' style='width:50px;height:50px;background:#333;color:#fff;text-align:center;line-height:50px'>小妖</div>
</body>
Paste_Image.png

紫金葫蘆里面的源碼大概是這樣的:

var 紫金葫蘆 = function(id){
    var domElement = document.getElementById(id);
    
    var returnObject = {

        domElement : domElement ,

        backgroundColor : function(color){
            domElement.style.backgroundColor = color;
        },

        click : function(fn){
            domElement.onclick = fn;
        }
    };
    
    return returnObject;
}

注:我純粹是為了看起來方便而采用中文定義變量菌赖,在實(shí)際開發(fā)中,千萬不要使用中文變量沐序。

我們?cè)诜祷爻鋈サ膶?duì)象上加了三個(gè)東西:

1.domElement
你傳進(jìn)來一個(gè)id琉用,我就用 document.getElementById 來包一下堕绩,得到一個(gè)dom元素,最終要操作的也就是這個(gè)dom元素邑时。也就是說:

var box1 = 紫金葫蘆('box').domElement;
var box2 = document.getElementById('box');
alert(box1 === box2);
Paste_Image.png

他們是一個(gè)東西奴紧,一樣的。

紫金葫蘆('box');

這行代碼一旦執(zhí)行晶丘,紫金葫蘆就會(huì)返回 returnObject 對(duì)象黍氮,也就是說。我們喊一聲 “box”浅浮,那個(gè)id為box的小妖一答應(yīng)沫浆,就被裝進(jìn)來了,然后我們可以對(duì)它為所欲為滚秩!

比如专执,給它換一個(gè)背景色:

2.backgroundColor 給元素添加背景色的方法

var box = 紫金葫蘆('box');
box.backgroundColor('red');
Paste_Image.png

3.click 給元素添加點(diǎn)擊事件,需要傳入一個(gè)回調(diào)函數(shù)

var box = 紫金葫蘆('box');
box.click(function(){
    alert('就沒人吐槽這個(gè)無聊的作者么郁油,小妖也有尊嚴(yán)的好么本股,啊喂!桐腌!');
});

結(jié)果:

click.gif

也許你已經(jīng)發(fā)現(xiàn)了拄显,這些方法是不是和jQuery有點(diǎn)類似呢?

本章結(jié)束 ...

剽悍一小兔哩掺,電氣自動(dòng)化畢業(yè)凿叠。
參加工作后對(duì)計(jì)算機(jī)感興趣,深知初學(xué)編程之艱辛嚼吞。
希望將自己所學(xué)記錄下來盒件,給初學(xué)者一點(diǎn)幫助。

免責(zé)聲明: 博客中所有的圖片素材均來自百度搜索舱禽,僅供學(xué)習(xí)交流炒刁,如有問題請(qǐng)聯(lián)系我,侵立刪誊稚,謝謝翔始。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市里伯,隨后出現(xiàn)的幾起案子城瞎,更是在濱河造成了極大的恐慌,老刑警劉巖疾瓮,帶你破解...
    沈念sama閱讀 206,482評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件脖镀,死亡現(xiàn)場離奇詭異,居然都是意外死亡狼电,警方通過查閱死者的電腦和手機(jī)蜒灰,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,377評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門弦蹂,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人强窖,你說我怎么就攤上這事凸椿。” “怎么了翅溺?”我有些...
    開封第一講書人閱讀 152,762評(píng)論 0 342
  • 文/不壞的土叔 我叫張陵脑漫,是天一觀的道長。 經(jī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
  • 文/蒼蘭香墨 我猛地睜開眼荠察,長吁一口氣:“原來是場噩夢(mèng)啊……” “哼!你這毒婦竟也來了奈搜?” 一聲冷哼從身側(cè)響起悉盆,我...
    開封第一講書人閱讀 36,988評(píng)論 0 259
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎馋吗,沒想到半個(gè)月后焕盟,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,476評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡耗美,尸身上長有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
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至嵌牺,卻和暖如春打洼,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背逆粹。 一陣腳步聲響...
    開封第一講書人閱讀 31,486評(píng)論 1 262
  • 我被黑心中介騙來泰國打工募疮, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人枯饿。 一個(gè)月前我還...
    沈念sama閱讀 45,511評(píng)論 2 354
  • 正文 我出身青樓酝锅,卻偏偏與公主長得像,于是被迫代替她去往敵國和親奢方。 傳聞我的和親對(duì)象是個(gè)殘疾皇子搔扁,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,802評(píng)論 2 345

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

  • JavaScript: 零基礎(chǔ)輕松學(xué)閉包 參考鏈接 JavaScript: 零基礎(chǔ)輕松學(xué)閉包(1)http://w...
    kakukeme閱讀 693評(píng)論 0 50
  • 注:本人發(fā)布的所有文章均為原創(chuàng),未經(jīng)作者許可蟋字,切勿轉(zhuǎn)載稿蹲,謝謝。 本文面向初學(xué)者鹊奖,大神輕噴苛聘。 閉包是什么? 初學(xué)ja...
    剽悍一小兔閱讀 2,031評(píng)論 42 65
  • Python基礎(chǔ)語法學(xué)習(xí)(基礎(chǔ)知識(shí))HTML頁面的內(nèi)容抓取(數(shù)據(jù)抓壬杌)HTML頁面的數(shù)據(jù)提瘸贰(數(shù)據(jù)清洗)Scrap...
    彡廿閱讀 3,475評(píng)論 0 1
  • 父母對(duì)其中一個(gè)子女的態(tài)度會(huì)影響到其他子女的對(duì)她們父母感覺的看法。是不是爭吵网梢,久而久之震缭,其他人都能夠提前感應(yīng)到狂風(fēng)暴...
    簡簡單單shapy閱讀 181評(píng)論 0 0
  • 媽媽, 您時(shí)刻都能讓我感到你的愛战虏; 在您早早起床為我做飯的時(shí)候拣宰, 在您耐心開導(dǎo)我所不解的事的時(shí)候, 在您...
    安亦年閱讀 618評(píng)論 0 2