国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學(xué)院 > 開發(fā)設(shè)計(jì) > 正文

js中bind、call、apply函數(shù)的用法

2019-11-06 09:44:03
字體:
供稿:網(wǎng)友

最近一直在用 js 寫游戲服務(wù)器,我也接觸 js 時(shí)間不長,大學(xué)的時(shí)候用 js 做過一個(gè) H3C 的 web 的項(xiàng)目,然后在騰訊實(shí)習(xí)的時(shí)候用 js 寫過一些奇怪的程序,自己也用 js 寫過幾個(gè)的網(wǎng)站。但真正大規(guī)模的使用 js 這還是第一次。我也是初生牛犢不怕虎,這次服務(wù)器居然拋棄 C++ 和 lua 的正統(tǒng)搭配,而嘗試用 nodejs 來寫游戲服務(wù)器,折騰的自己要死要活的我也是醉了。

在給我們項(xiàng)目組的其他程序介紹 js 的時(shí)候,我準(zhǔn)備了很多的內(nèi)容,但看起來效果不大,果然光講還是不行的,必須動手。前幾天有人問我關(guān)于代碼里 call() 函數(shù)的用法,我讓他去看書,這里推薦用 js 寫服務(wù)器的程序猿看 《javascript編程精粹》 這本書,crockford大神果然不是蓋的。之后我在 segmentfault 上又看到了類似的問題,那邊解答之后干脆這里記一筆。

首先,關(guān)于 js 定義類或?qū)ο蟮姆椒ǎ垍⒖?nbsp;vevb 的這里,寫的非常詳細(xì)和清晰,我不再贅言了。

為了介紹 bind、call、apply 這三個(gè)函數(shù)的用法,不得不介紹 js 里函數(shù)的一些設(shè)定。關(guān)于這部分推薦通讀 《Javascript編程精粹》 的第四章,這里我所說的在書里都能找到。

關(guān)于這三個(gè)函數(shù)的詳細(xì)介紹,可以參看 MDN 的文檔:bind、call、apply。

下面開始搬磚,修改自我之前在 segmentfault 上的答案:

js 里函數(shù)調(diào)用有 4 種模式:方法調(diào)用、正常函數(shù)調(diào)用、構(gòu)造器函數(shù)調(diào)用、apply/call 調(diào)用。同時(shí),無論哪種函數(shù)調(diào)用除了你聲明時(shí)定義的形參外,還會自動添加 2 個(gè)形參,分別是 this 和 arguments。arguments 不涉及到上述 3 個(gè)函數(shù),所以這里只談 this。this 的值,在上面 4 中調(diào)用模式下,分別會綁定不同的值。分別來說一說:方法調(diào)用:這個(gè)很好理解,函數(shù)是一個(gè)對象的屬性,比如

1234567var a = {        v : 0,        f : function(xx) {                        this.v = xx;        }}a.f(5);

這個(gè)時(shí)候,上面函數(shù)里的 this 就綁定的是這個(gè)對象 a。所以 this.v 可以取到對象 a 的屬性 v。

正常函數(shù)調(diào)用:依然看代碼

1234function f(xx) {            this.x = xx;}f(5);

這個(gè)時(shí)候,函數(shù) f 里的 this 綁定的是全局對象,如果是在瀏覽器運(yùn)行的解釋器中,一般來說是 window 對象。所以這里 this.x 訪問的其實(shí)是 window.x ,當(dāng)然,如果 window 沒有 x 屬性,那么你這么一寫,按照 js 的坑爹語法,就是給 window 對象添加了一個(gè) x 屬性,同時(shí)賦值。

構(gòu)造器函數(shù)調(diào)用:構(gòu)造函數(shù)一直是我認(rèn)為是 js 里最坑爹的部分,因?yàn)樗?nbsp;js 最初設(shè)計(jì)的基于原型的面向?qū)ο髮?shí)現(xiàn)方式格格不入,就好像是特意為了迎合大家已經(jīng)被其他基于類的面相對象實(shí)現(xiàn)給慣壞了的習(xí)慣。如果你在一個(gè)函數(shù)前面帶上 new 關(guān)鍵字來調(diào)用,那么 js 會創(chuàng)建一個(gè) PRototype 屬性是此函數(shù)的一個(gè)新對象,同時(shí)在調(diào)用這個(gè)函數(shù)的時(shí)候,把 this 綁定到這個(gè)新對象上。當(dāng)然 new 關(guān)鍵字也會改變 return 語句的行為,不過這里就不談了。看代碼

1234function a(xx) {            this.m = xx;}var b = new a(5);

上面這個(gè)函數(shù)和正常調(diào)用的函數(shù)寫法上沒什么區(qū)別,只不過在調(diào)用的時(shí)候函數(shù)名前面加了關(guān)鍵字 new 罷了,這么一來,this 綁定的就不再是前面講到的全局對象了,而是這里說的創(chuàng)建的新對象,所以說這種方式其實(shí)很危險(xiǎn),因?yàn)楣饪春瘮?shù),你不會知道這個(gè)函數(shù)到底是準(zhǔn)備拿來當(dāng)構(gòu)造函數(shù)用的,還是一般函數(shù)用的。所以我們可以看到,在 jslint 里,它會要求你寫的所有構(gòu)造函數(shù),也就是一旦它發(fā)現(xiàn)你用了 new 關(guān)鍵字,那么后面那個(gè)函數(shù)的首字母必須大寫,這樣通過函數(shù)首字母大寫的方式來區(qū)分,我個(gè)人只有一個(gè)看法:坑爹:)

apply/call 調(diào)用:我們知道,在 js 里,函數(shù)其實(shí)也是一個(gè)對象,那么函數(shù)自然也可以擁有它自己的方法,有點(diǎn)繞,在 js 里,每個(gè)函數(shù)都有一個(gè)公共的 prototype —— Function,而這個(gè)原型自帶有好幾個(gè)屬性和方法,其中就有這里困惑的 bind、call、apply 方法。先說 apply 方法,它讓我們構(gòu)造一個(gè)參數(shù)數(shù)組傳遞給函數(shù),同時(shí)可以自己來設(shè)置 this 的值,這就是它最強(qiáng)大的地方,上面的 3 種函數(shù)調(diào)用方式,你可以看到,this 都是自動綁定的,沒辦法由你來設(shè),當(dāng)你想設(shè)的時(shí)候,就可以用 apply() 了。apply 函數(shù)接收 2 個(gè)參數(shù),第一個(gè)是傳遞給這個(gè)函數(shù)用來綁定 this 的值,第二個(gè)是一個(gè)參數(shù)數(shù)組。看代碼

1234567function a(xx) {            this.b = xx;}var o = {};a.apply(o, [5]);alert(a.b);    // undefinedalert(o.b);    // 5

是不是很神奇,函數(shù) a 居然可以給 o 加屬性值。當(dāng)然,如果你 apply 的第一個(gè)參數(shù)傳遞 null,那么在函數(shù) a 里面 this 指針依然會綁定全局對象。

call() 方法和 apply() 方法很類似,它們的存在都是為了改變 this 的綁定,那 call() 和 apply() 有什么區(qū)別呢?就我個(gè)人看來,沒啥鳥區(qū)別。。。開玩笑!剛剛說了,上面 apply() 接收兩個(gè)參數(shù),第一個(gè)是綁定 this 的值,第二個(gè)是一個(gè)參數(shù)數(shù)組,注意它是一個(gè)數(shù)組,你想傳遞給這個(gè)函數(shù)的所有參數(shù)都放在數(shù)組里,然后 apply() 函數(shù)會在調(diào)用函數(shù)時(shí)自動幫你把數(shù)組展開。而 call() 呢,它的第一個(gè)參數(shù)也是綁定給 this 的值,但是后面接受的是不定參數(shù),而不再是一個(gè)數(shù)組,也就是說你可以像平時(shí)給函數(shù)傳參那樣把這些參數(shù)一個(gè)一個(gè)傳遞。所以如果一定要說有什么區(qū)別的話,看起來是這樣的

1234567function a(xx, yy) {        alert(xx, yy);        alert(this);        alert(arguments);}a.apply(null, [5, 55]);a.call(null, 5, 55);

僅此而已。

最后再來說 bind() 函數(shù),上面講的無論是 call() 也好, apply() 也好,都是立馬就調(diào)用了對應(yīng)的函數(shù),而 bind() 不會, bind() 會生成一個(gè)新的函數(shù),bind() 函數(shù)的參數(shù)跟 call() 一致,第一個(gè)參數(shù)也是綁定 this 的值,后面接受傳遞給函數(shù)的不定參數(shù)。 bind() 生成的新函數(shù)返回后,你想什么時(shí)候調(diào)就什么時(shí)候調(diào),看下代碼就明白了

12345678910var m = {       "x" : 1};function foo(y) {    alert(this.x + y);}foo.apply(m, [5]);foo.call(m, 5);var foo1 = foo.bind(m, 5);foo1();

末了來個(gè)吐槽,你在 js 里想定義一個(gè)函數(shù),于是你會這么寫:

1function jam() {};

其實(shí)這是 js 里的一種語法糖,它等價(jià)于:

1var jam = function() {};

然后你想執(zhí)行這個(gè)函數(shù),腦洞大開的你會這么寫:

1function jam() {}();

但是這么寫就報(bào)錯了,其實(shí)這種寫法也不算錯,因?yàn)樗_實(shí)是 js 支持的函數(shù)表達(dá)式,但是同時(shí) js 又規(guī)定以 function 開頭的語句被認(rèn)為是函數(shù)語句,而函數(shù)語句后面是肯定不會帶 () 的,所以才報(bào)錯,于是聰明的人想出來,加上一對括號就可以了。于是就變成了這樣:

1(function jam() {}());

這樣就定義了一個(gè)函數(shù)同時(shí)也執(zhí)行它,詳情參見 ECMAScript 的 Expression Statement 章節(jié)。

本文出自 “菜鳥浮出水” 博客,請務(wù)必保留此出處http://rangercyh.blog.51cto.com/1444712/1615809


發(fā)表評論 共有條評論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 南涧| 泉州市| 稷山县| 鄢陵县| 志丹县| 兴仁县| 北流市| 慈溪市| 永和县| 赣榆县| 娄烦县| 姜堰市| 阆中市| 理塘县| 栾川县| 杭州市| 突泉县| 天峨县| 巴马| 柳江县| 额济纳旗| 平舆县| 南郑县| 临潭县| 延吉市| 顺义区| 全椒县| 漠河县| 汶上县| 澄江县| 精河县| 东方市| 贺州市| 长治县| 康保县| 昭平县| 潜江市| 阿瓦提县| 太原市| 滨州市| 佛冈县|