溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

JavaScript中的工廠函數(shù)(推薦)

發(fā)布時(shí)間:2020-10-18 11:01:17 來(lái)源:腳本之家 閱讀:119 作者:落葉的博客 欄目:web開發(fā)

JavaScript中的工廠函數(shù)(推薦)

在學(xué)習(xí)jQuery的時(shí)候,我們經(jīng)常會(huì)看到“工廠函數(shù)”這個(gè)概念,那么究竟什么是“工廠函數(shù)”呢?我們來(lái)看看概念,“所謂工廠函數(shù),就是指這些內(nèi)建函數(shù)都是類對(duì)象,當(dāng)你調(diào)用他們時(shí),實(shí)際上是創(chuàng)建了一個(gè)類實(shí)例”。意思就是當(dāng)我調(diào)用這個(gè)函數(shù),實(shí)際上是先利用類創(chuàng)建了一個(gè)對(duì)象,然后返回這個(gè)對(duì)象。由于Javascript本身不是嚴(yán)格的面向?qū)ο蟮恼Z(yǔ)言(不包含類),實(shí)際上來(lái)說(shuō),Javascript并沒有嚴(yán)格的“工廠函數(shù)”,但是在Javascript中,我們能利用函數(shù)模擬類。

我們首先通過(guò)new關(guān)鍵字創(chuàng)建了一個(gè)對(duì)象,obj就相當(dāng)于Object的實(shí)例。我們通過(guò)類實(shí)例化了一個(gè)對(duì)象,然后給這個(gè)對(duì)象相應(yīng)的屬性,最后返回對(duì)象。我們可以通過(guò)調(diào)用這個(gè)函數(shù)來(lái)創(chuàng)建對(duì)象,這樣的話,實(shí)際上工廠函數(shù)也很好理解了:

1,它是一個(gè)函數(shù)。

2,它用來(lái)創(chuàng)建對(duì)象。

3,它像工廠一樣,“生產(chǎn)”出來(lái)的函數(shù)都是“標(biāo)準(zhǔn)件”(擁有同樣的屬性)

不學(xué)習(xí)函數(shù)和對(duì)象,你不可能成為一名JavaScript程序員,并且當(dāng)他們一起使用時(shí),是構(gòu)建塊,我們需要從一個(gè)稱為 組合(composition) 的強(qiáng)大對(duì)象范例開始。今天我們來(lái)看一些慣用的模式,使用工廠函數(shù)來(lái)組成函數(shù),對(duì)象和 Promises 。組合模式是將一批子對(duì)象組織為樹形結(jié)構(gòu),一條頂層的命令會(huì)在操作樹中所有的對(duì)象。當(dāng)一個(gè)函數(shù)返回一個(gè)對(duì)象時(shí),我們稱之他為 工廠函數(shù)(factory function) 。

    讓我們來(lái)看一個(gè)簡(jiǎn)單的例子。

function createJelly() {
 return {
 type: 'jelly',
 colour: 'red'
 scoops: 3
 };
 }

下面我們通過(guò)一些實(shí)例給大家介紹。

    每次我們調(diào)用這個(gè)工廠函數(shù),它將返回一個(gè)新的 jelly(果凍) 對(duì)象實(shí)例。要注意的重點(diǎn)是,我們不必在工廠函數(shù)名稱前面加上 create ,但它可以讓其他人更清楚函數(shù)的意圖。對(duì)于 type 屬性也是如此,但通常它可以幫助我們區(qū)分我們程序的對(duì)象。   

    1.帶參數(shù)的工廠函數(shù)

    像所有函數(shù)一樣,我們可以通過(guò)參數(shù)來(lái)定義我們的工廠函數(shù) (icecream 冰淇淋),這可以用來(lái)改變返回對(duì)象的模型。

function createIceCream(flavour='Vanilla') {
 return {
 type: 'icecream',
 scoops: 3,
 flavour
 }
 }

    理論上,您可以使用帶有數(shù)百個(gè)參數(shù)的工廠函數(shù)來(lái)返回非常特使的深層嵌套對(duì)象,但正如我們將看到的,這根本不是組合的精髓。

    2.組合的工廠函數(shù)

    在一個(gè)工廠函數(shù)中定義另一個(gè)工廠函數(shù),可以幫助我們把復(fù)雜的工廠函數(shù)拆分成更小的,可重用的碎片。

    例如,我們可以創(chuàng)建一個(gè) dessert(甜點(diǎn))工廠函數(shù),通過(guò)前面的 jelly(果凍)和 icecream(冰淇淋)工廠函數(shù)來(lái)定義。    

 function createDessert() {
 return {
 type: 'dessert',
 bowl: [
 createJelly(),
 createIceCream()
 ]
 };
 }

    我們可以組合工廠函數(shù)來(lái)構(gòu)建任意復(fù)雜的對(duì)象,這不需要我們結(jié)合使用 new 或 this 。對(duì)象可以用 has-a (具有) 關(guān)系而不是 is-a (是) 來(lái)表示。也就是說(shuō),可以用組合而不是繼承來(lái)實(shí)現(xiàn)。    

    例如,使用繼承。

 // A trifle *is a* dessert 蛋糕*是*甜點(diǎn)
 function Trifle() {
 Dessert.apply(this, arguments);
 }
 Trifle.prototype = Dessert.prototype;
 // 或者
 class Trifle extends Dessert {
 constructor() {
 super();
 }
 }

   我們可以用組合模式表達(dá)相同的意思。

 // A trifle *has* layers of jelly, custard and cream. It also *has a* topping.
 // 蛋糕 *有* 果凍層,奶酪層和奶油層,頂部還 *有* 裝飾配料。
 function createTrifle() {
 return {
 type: 'trifle',
 layers: [
 createJelly(),
 createCustard(),
 createCream()
 ],
 topping: createAlmonds()
 };
 }

    3.異步的工廠函數(shù)

    并非所有工廠都會(huì)立即返回?cái)?shù)據(jù)。例如,有些必須先獲取數(shù)據(jù)。在這些情況下,我們可以返回 Promises 來(lái)定義工廠函數(shù)。  

function getMeal(menuUrl) {
 return new Promise((resolve, reject) => {
 fetch(menuUrl)
 .then(result => {
 resolve({
 type: 'meal',
 courses: result.json()
 });
 })
 .catch(reject);
 });
 }

    這種深度嵌套的縮進(jìn)會(huì)使異步工廠難以閱讀和測(cè)試。將它們分解成多個(gè)不同的工廠通常是有幫助的,可以使用如下編寫。

function getMeal(menuUrl) {
 return fetch(menuUrl)
 .then(result => result.json())
 .then(json => createMeal(json));
 }
 function createMeal(courses=[]) {
 return {
 type: 'meal',
 courses
 };
 }

    當(dāng)然,我們可以使用回調(diào)函數(shù),但是我們已經(jīng)有了 Promise.all 這樣的工具返回 Promises 來(lái)定義工廠函數(shù)。    

 function getWeeksMeals() {
 const menuUrl = 'jsfood.com/';
 return Promise.all([
 getMeal(`${menuUrl}/monday`),
 getMeal(`${menuUrl}/tuesday`),
 getMeal(`${menuUrl}/wednesday`),
 getMeal(`${menuUrl}/thursday`),
 getMeal(`${menuUrl}/friday`)
 ]);
 }

    我們使用 get 而不是 create 作為命名約定來(lái)顯示這些工廠做一些異步工作和返回promise。

    4.函數(shù)和方法

    到目前為止,我們還沒有看到任何工廠用方法返回對(duì)象,這是故意的。這是因?yàn)橐话銇?lái)說(shuō),我們不需要這么做。工廠允許我們從計(jì)算中分離我們的數(shù)據(jù)。這意味著我們總是能夠?qū)?duì)象序列化為JSON,這對(duì)于在會(huì)話之間持久化,通過(guò)HTTP或WebSockets發(fā)送它們,并將它們放入數(shù)據(jù)存儲(chǔ)很重要。

    例如,不是在 jelly(果凍) 對(duì)象上定義 eat 方法,我們可以定義一個(gè)新的函數(shù),它接受一個(gè)對(duì)象作為參數(shù)并返回一個(gè)修改的版本。 

function eatJelly(jelly) {
 if(jelly.scoops > 0) {
 jelly.scoops -= 1;
 }
 return jelly;
 }

    一點(diǎn)點(diǎn)句法幫助使這是一個(gè)可行的模式,那些喜歡編程而不改變數(shù)據(jù)結(jié)構(gòu)的人。對(duì)于那些喜歡編程而不改變數(shù)據(jù)結(jié)構(gòu)的人來(lái)說(shuō),使用 ES6 的 ... 語(yǔ)法 是一個(gè)可行的模式。   

 function eat(jelly) {
 if(jelly.scoops > 0) {
 return { ...jelly, scoops: jelly.scoops - 1 };
 } else {
 return jelly;
 }
 }

    現(xiàn)在,不是這樣寫:

 import { createJelly } from './jelly';
 createJelly().eat();

    而是這樣寫   

 import { createJelly, eatJelly } from './jelly';
 eatJelly(createJelly()); 

 

    最終結(jié)果是一個(gè)函數(shù),它接受一個(gè)對(duì)象并返回一個(gè)對(duì)象。我們稱之為返回對(duì)象的函數(shù)是什么? 一個(gè)工廠!  

    5.高級(jí)工廠

    將工廠傳遞給 高階函數(shù) ,這將給我們帶來(lái)巨大的控制力。例如,我們可以使用這個(gè)概念來(lái)創(chuàng)建一個(gè)增強(qiáng)的對(duì)象。   

 function giveTimestamp(factory) {
 return (...args) => {
 const instance = factory(...args);
 const time = Date.now();
 return { time, instance };
 };
 }
 const createOrder = giveTimestamp(function(ingredients) {
 return {
 type: 'order',
 ingredients
 };
 });

    這個(gè)增強(qiáng)的對(duì)象采用一個(gè)現(xiàn)有工廠,并將其包裝以創(chuàng)建返回帶有時(shí)間戳實(shí)例的工廠?;蛘撸绻覀兿胍_保一個(gè)工廠返回不可變的對(duì)象,我們可以用 freezer 來(lái)增強(qiáng)它。    

 function freezer(factory) {
 return (...args) => Object.freeze(factory(...args)));
 }
 const createImmutableIceCream = freezer(createIceCream);
 createImmutableIceCream('strawberry').flavour = 'mint'; // Error!

    6.結(jié)論

    作為一個(gè) 聰明的程序員 曾經(jīng)說(shuō)過(guò):從沒有抽象比錯(cuò)誤的抽象更容易回收。JavaScript項(xiàng)目有一個(gè)趨勢(shì),變得難以測(cè)試和重構(gòu),因?yàn)槲覀兘?jīng)常鼓勵(lì)使用復(fù)雜的抽象層。原型和類實(shí)現(xiàn)一個(gè)簡(jiǎn)單的想法使用復(fù)雜和不人性的工具,如 new 和 this ,即使現(xiàn)在,這仍然引起 各種各樣的困惑 -幾年后他們被添加到語(yǔ)言。對(duì)象和函數(shù)對(duì)于來(lái)自大多數(shù)語(yǔ)言背景的程序員來(lái)說(shuō)是有意義的,并且都是JavaScript中的原始類型,所以可以說(shuō)工廠不是抽象的!對(duì)象和函數(shù)對(duì)來(lái)自大多數(shù)背景的程序員都有意義,并且都是JavaScript中的原始類型,所以可以說(shuō)工廠不是抽象的!使用這些簡(jiǎn)單的構(gòu)建塊使得我們的代碼對(duì)于沒有經(jīng)驗(yàn)的程序員更加友好,這絕對(duì)是我們應(yīng)該關(guān)心的事情。工廠鼓勵(lì)我們用原始數(shù)據(jù)來(lái)模擬復(fù)雜和異步數(shù)據(jù),原始數(shù)據(jù)具有組合的自然能力,而不強(qiáng)迫我們?nèi)プ鲆恍└呒?jí)抽象。 當(dāng)我們堅(jiān)持簡(jiǎn)單時(shí),JavaScript更甜蜜!

以上所述是小編給大家介紹的JavaScript中的工廠函數(shù),希望對(duì)大家有所幫助,如果大家有任何疑問請(qǐng)給我留言,小編會(huì)及時(shí)回復(fù)大家的。在此也非常感謝大家對(duì)億速云網(wǎng)站的支持!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI