摘要:所以,這篇文章將通過(guò)一段非常簡(jiǎn)潔的等式,把當(dāng)中一個(gè)相對(duì)較難的知識(shí)點(diǎn),,和給串聯(lián)起來(lái)要理解當(dāng)中的這三個(gè)關(guān)鍵字,首先得弄清楚它們是用來(lái)干嘛的。方案讓吃掉,直接消化吸收的所有能力。
關(guān)于JS當(dāng)中的call,apply和bind,相信大家和我一樣,已經(jīng)看過(guò)了無(wú)數(shù)篇相關(guān)的文章,都有自己的理解。所以這篇文章并非什么科普類的文章,僅僅是把我自己的理解記錄下來(lái)。
我的學(xué)習(xí)習(xí)慣,是喜歡把各種看似孤立的知識(shí)點(diǎn)串聯(lián)起來(lái),綜合理解并運(yùn)用,通過(guò)最簡(jiǎn)單最直觀的思路把它理解透。所以,這篇文章將通過(guò)一段非常簡(jiǎn)潔的等式,把JS當(dāng)中一個(gè)相對(duì)較難的知識(shí)點(diǎn),call,apply和bind給串聯(lián)起來(lái):
cat.call(dog, a, b) = cat.apply(dog, [a, b]) = (cat.bind(dog, a, b))() = dog.cat(a, b)
要理解JS當(dāng)中的這三個(gè)關(guān)鍵字,首先得弄清楚它們是用來(lái)干嘛的。復(fù)雜些來(lái)說(shuō),可以引用MDN文檔的原文:
可以讓call()中的對(duì)象調(diào)用當(dāng)前對(duì)象所擁有的function。你可以使用call()來(lái)實(shí)現(xiàn)繼承:寫一個(gè)方法,然后讓另外一個(gè)新的對(duì)象來(lái)繼承它(而不是在新對(duì)象中再寫一次這個(gè)方法)。
簡(jiǎn)單些來(lái)說(shuō),可以引用大家都看過(guò)的一句話:
為了動(dòng)態(tài)改變某個(gè)函數(shù)運(yùn)行時(shí)的上下文(context)。
又或者是
為了改變函數(shù)體內(nèi)部this的指向
上面這些解釋都很正確,說(shuō)得一點(diǎn)問(wèn)題都沒(méi)有,但是里面卻又引入了繼承,上下文,this這些額外的知識(shí)點(diǎn)。如果我只想用最直觀的辦法去理解這三個(gè)關(guān)鍵字的作用,也許可以這么去理解:
定義一個(gè)貓對(duì)象:
class Cat { constructor (name) { this.name = name } catchMouse(name1, name2) { console.log(`${this.name} caught 2 mouse! They call ${name1} and ${name2}.`) } }
這個(gè)貓對(duì)象擁有一個(gè)抓老鼠的技能catchMouse()。
然后類似的,定義一個(gè)狗對(duì)象:
class Dog { constructor (name) { this.name = name } biteCriminals(name1, name2) { console.log(`${this.name} bite 2 criminals! Their name is ${name1} and ${name2}.`) } }
這個(gè)狗對(duì)象能夠咬壞人biteCriminal()。
接下來(lái),我們實(shí)例化兩個(gè)對(duì)象,分別得到一只叫“Kitty”的貓和叫“Doggy”的狗:
const kitty = new Cat("Kitty") const doggy = new Dog("Doggy")
首先讓它們彼此發(fā)揮自己的技能:
kitty.catchMouse("Mickey", "Minnie") // Kitty caught mouse! They call Mickey and Minnie. doggy.biteCriminal("Tom", "Jerry") // Doggy bite a criminal! Their name is Tom and Jerry.
現(xiàn)在,我們希望賦予Doggy抓老鼠的能力,如果不使用這三個(gè)關(guān)鍵字,應(yīng)該怎么做呢?
方案A:修改Dog對(duì)象,直接為其定義一個(gè)和Cat相同的抓老鼠技能。
方案B:讓Doggy吃掉Kitty,直接消化吸收Kitty的所有能力。
其實(shí)方案A和方案B的解決辦法是類似的,也是需要修改Dog對(duì)象,不過(guò)方案B會(huì)更簡(jiǎn)單粗暴一點(diǎn):
class Dog { constructor (name, kitty) { this.name = name this.catchMouse = kitty.catchMouse } biteCriminals(name1, name2) { console.log(`${this.name} bite 2 criminals! Their name is ${name1} and ${name2}.`) } } const kitty = new Cat("Kitty") const doggy = new Dog("Doggy", kitty) doggy.catchMouse("Mickey", "Minnie") // Doggy caught 2 mouse! They call Mickey and Minnie.
上面這種方法實(shí)在是太不優(yōu)雅,往往很多時(shí)候在定義Dog對(duì)像的時(shí)候根本就沒(méi)有打算過(guò)要為它添加抓老鼠的方法。那么有沒(méi)有一種辦法能夠在不修改Dog對(duì)象內(nèi)容的前提下,讓Doggy實(shí)例也能夠擁有抓老鼠的辦法呢?答案就是使用call,apply或者bind關(guān)鍵字:
kitty.catchMouse.call(doggy, "Mickey", "Minnie") kitty.catchMouse.apply(doggy, ["Mickey", "Minnie"]) const doggyCatchMouse = kitty.catchMouse.bind(doggy, "Mickey", "Minnie") doggyCatchMouse() // Doggy caught 2 mouse! They call Mickey and Minnie. // Doggy caught 2 mouse! They call Mickey and Minnie. // Doggy caught 2 mouse! They call Mickey and Minnie.
反過(guò)來(lái),讓Kitty擁有咬壞人的能力,也可以通過(guò)這種辦法實(shí)現(xiàn),讀者可以自行嘗試。
看到這里,相信讀者已經(jīng)能夠明白call,apply和bind的區(qū)別及作用,反過(guò)來(lái)再查看各自的概念,應(yīng)該也能夠更容易理解。
回到文章開頭的等式:
cat.call(dog, a, b) = cat.apply(dog, [a, b]) = (cat.bind(dog, a, b))() = dog.cat(a, b)
這里的“等號(hào)”其實(shí)并不嚴(yán)謹(jǐn),因?yàn)槿齻€(gè)關(guān)鍵字的區(qū)別及背后的原理肯定不是區(qū)區(qū)一個(gè)等號(hào)就能夠概括的,但是對(duì)于概念的理解以及實(shí)際情況下的運(yùn)用來(lái)說(shuō),這條等式未必不是一個(gè)好的思路。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/93964.html
摘要:關(guān)于的指向的問(wèn)題請(qǐng)參照我的學(xué)習(xí)筆記。那么在這里事實(shí)上都改變了函數(shù)方法被調(diào)用時(shí)的指向。那么回調(diào)函數(shù)在執(zhí)行的時(shí)候指向還是。大家看完之后應(yīng)該已經(jīng)懂了把還是不懂的話在評(píng)論區(qū)留言,我給大家解答。 先從一個(gè)小題目開始吧: 要實(shí)現(xiàn)一個(gè)加法函數(shù),這個(gè)時(shí)候向函數(shù)當(dāng)中傳遞個(gè)數(shù)大于0的若干個(gè)整形數(shù)據(jù),求所有這些數(shù)據(jù)的和。 Function.prototype.call Function.prototype...
摘要:目錄函數(shù)的聲明函數(shù)的屬性和方法函數(shù)的作用域閉包知識(shí)點(diǎn)小結(jié)關(guān)于函數(shù),可以從以下個(gè)方面去理解首先,數(shù)據(jù)類型上看函數(shù)在中是一種數(shù)據(jù)類型,是對(duì)象的一種其次,從功能上看函數(shù)本質(zhì)上是一段反復(fù)調(diào)用的代碼塊最后,從地位上看函數(shù)在中和其他基本數(shù)據(jù)類型一樣,可 目錄 1.函數(shù)的聲明 2.函數(shù)的屬性和方法 3.函數(shù)的作用域 4.閉包知識(shí)點(diǎn) 5.小結(jié) 關(guān)于函數(shù),可以從以下3個(gè)方面去理解:首先,數(shù)據(jù)類型上看:...
摘要:而當(dāng)做普通函數(shù)調(diào)用的話,實(shí)際上即第種情況下,對(duì)函數(shù)普通調(diào)用,此時(shí)的指向這是正常情況下,會(huì)正確返回并且指向該對(duì)象,但是在構(gòu)造函數(shù)當(dāng)中,如果返回了一個(gè)對(duì)象,那么會(huì)指向返回的那個(gè)對(duì)象。 this應(yīng)該是一個(gè)討論了很久的話題了。其中,關(guān)于this的文章,在很多的博客當(dāng)中也有很多介紹,但是,以前我都是一知半解的去了解它,就是看博客當(dāng)中,只介紹了一些情況下的 this 的使用方式,但是也并沒(méi)有自己去...
摘要:回顧一下關(guān)鍵詞的過(guò)程創(chuàng)建一個(gè)新的對(duì)象使得的指向構(gòu)造函數(shù)的原型對(duì)象執(zhí)行構(gòu)造函數(shù)中的,改變的指向?yàn)槿绻Y(jié)果是對(duì)象類型,則返回結(jié)果,否則返回指向的是調(diào)用時(shí)傳遞的第一個(gè)參數(shù)。 this = ? 在JS中,當(dāng)一個(gè)函數(shù)執(zhí)行時(shí),都會(huì)創(chuàng)建一個(gè)執(zhí)行上下文用來(lái)確認(rèn)當(dāng)前函數(shù)的執(zhí)行環(huán)境,執(zhí)行上下文分為 全局執(zhí)行上下文和 函數(shù)執(zhí)行上下文。而 this 就是指向這個(gè)執(zhí)行上下文的對(duì)象。所以,this是在運(yùn)行時(shí)決定的...
摘要:原文鏈接參考深入理解原型和閉包完結(jié)王福朋博客園中的作用域詳解博客園 前言 王福朋老師的 JavaScript原型和閉包系列 文章看了不下三遍了,最為一個(gè)初學(xué)者,每次看的時(shí)候都會(huì)有一種 大徹大悟 的感覺,而看完之后卻總是一臉懵逼。原型與閉包 可以說(shuō)是 JavaScirpt 中理解起來(lái)最難的部分了,當(dāng)然,我也只是了解到了一些皮毛,對(duì)于 JavaScript OOP 更是缺乏經(jīng)驗(yàn)。這里我想總...
閱讀 810·2021-11-25 09:43
閱讀 2162·2021-11-17 09:33
閱讀 976·2021-09-07 09:58
閱讀 2210·2021-08-16 10:52
閱讀 603·2019-08-30 15:52
閱讀 1880·2019-08-30 15:43
閱讀 1287·2019-08-30 15:43
閱讀 3054·2019-08-29 16:41