在 Javascript 中,沒(méi)有明確的類型檢查機(jī)制,這種特性就被稱作鴨子類型。
鴨子類型是基于一種假設(shè):如果某個(gè)對(duì)象像鴨子一樣走路、游泳、嘎嘎叫,那么我們就可以認(rèn)為它是一只鴨子。換句話說(shuō),只要對(duì)象有特定的行為表現(xiàn),我們就可以認(rèn)為它是某種類型。
<code>function makeSound(duck) { if(duck.hasOwnProperty('quack') && typeof duck.quack === 'function') { duck.quack(); } } </code>
例如,上面的代碼是一個(gè)接受一個(gè)對(duì)象參數(shù)的函數(shù),如果這個(gè)對(duì)象有quack
方法,那么讓對(duì)象調(diào)用方法。這里我們沒(méi)有關(guān)心對(duì)象的具體類型是什么,只需要它有一個(gè)quack
方法就可以。
由于 JavaScript 變量聲明時(shí)不需要指定類型, 所以可以在運(yùn)行期間動(dòng)態(tài)更改類型。 但是,如果我們要使用一個(gè)對(duì)象的屬性或方法,而它卻沒(méi)有實(shí)現(xiàn)這個(gè)屬性或方法,就會(huì)導(dǎo)致運(yùn)行時(shí)錯(cuò)誤。
<code>let duck = { quack: function() { console.log('嘎嘎嘎'); } }; let hand = { waddle: function() { console.log('quer quor'); } }; makeSound(duck);//"嘎嘎嘎" makeSound(hand);//類型錯(cuò)誤: hand.quack 不是一個(gè)函數(shù) </code>
在下面的例子中,我們聲明了一個(gè)鴨子對(duì)象和一個(gè)鵝對(duì)象,使用了相同的方法。當(dāng)我們把兩個(gè)對(duì)象傳入同一個(gè)函數(shù),它們都能夠遵循“這東西長(zhǎng)得像鴨子,聲音也像鴨子,就是一只鴨子”的邏輯運(yùn)行。
<code>let duck = { quack: function() { console.log('嘎嘎嘎!'); }, feathers: '褐色的羽毛' }; let goose = { honk: function() { console.log('嘎嘎嘎!'); }, feathers: '白色的羽毛' }; function duckJump(duck) { console.log('鴨子跳進(jìn)了池塘!'); } // 鴨子和鵝都可以使用 duckJump(duck); duckJump(goose); </code>
鴨子類型有一定的推動(dòng)力,在一定程度上實(shí)現(xiàn)多態(tài),減少了類型限制。 但是由于 JavaScript 缺少類型檢查,也帶來(lái)了一些缺點(diǎn),如果我們不注意代碼的可讀性和維護(hù)性,鴨子類型會(huì)對(duì)代碼的可靠性產(chǎn)生不良影響。
總而言之,鴨子類型在 JavaScript 中是一個(gè)非常有用的特性,使得編碼工作在特定的場(chǎng)景中變得更加簡(jiǎn)單方便。因此,當(dāng)我們不關(guān)心對(duì)象的具體類型,只關(guān)心其功能和屬性時(shí),可以用鴨子類型來(lái)概括實(shí)現(xiàn)接口和多態(tài)性操作。