首頁 web前端 js教程 詳解JavaScript中的工廠函數的範例程式碼

詳解JavaScript中的工廠函數的範例程式碼

Mar 22, 2017 pm 02:40 PM

所謂工廠函數,就是指這些內建函數都是類別對象,當你呼叫他們時,實際上是創建了一個類別實例。這篇文章主要介紹了JavaScript工廠函數,需要的朋友可以參考下

#在學習jQuery的時候,我們常常會看到「工廠函數」這個概念,那麼究竟什麼是「工廠函數」呢?讓我們來看看概念,「所謂工廠函數,就是指這些內建函數都是類別對象,當你呼叫他們時,實際上是創建了一個類別實例」。意思是當我呼叫這個函數,實際上是先利用類別創建了一個對象,然後返回這個對象。由於Javascript本身不是嚴格的物件導向的語言(不包含類別),實際上來說,Javascript並沒有嚴格的“工廠函數”,但是在Javascript中,我們可以利用函數來模擬類別。

我們先透過new關鍵字創建了一個對象,obj就相當於Object的實例。我們透過類別實例化了一個對象,然後給這個對象相應的屬性,最後返回對象。我們可以透過呼叫這個函數來創建對象,這樣的話,實際上工廠函數也很好理解了:

1,它是一個函數。

2,它用來建立物件。

3,它像工廠一樣,「生產」出來的函數都是「標準零件」(擁有相同的屬性)

不學習函數和對象,你不可能成為一名JavaScript程式設計師,並且當他們一起使用時,是構建塊,我們需要從一個稱為組合(composition) 的強大物件範例開始。今天我們來看一些慣用的模式,使用工廠函數來組成函數,物件和 Promises 。 組合模式是將一批子物件組織為樹狀結構,一條頂層的指令會在操作樹中所有的物件。當一個函數回傳一個物件時,我們稱之他為 工廠函數(factory function) 。

    讓我們來看一個簡單的例子。

function createJelly() {
 return {
 type: 'jelly',
 colour: 'red'
 scoops: 3
 };
 }
登入後複製

下面我們透過一些實例來跟大家介紹。

    每次我們呼叫這個工廠函數,它將傳回一個新的 jelly(果凍) 物件實例。要注意的重點是,我們不必在工廠函數名稱前面加上 create ,但它可以讓其他人更清楚函數的意圖。對於 type 屬性也是如此,但通常它可以幫助我們區分我們程式的物件。

    1.帶有參數的工廠函數

    就像所有函數一樣,我們可以透過參數定義我們的工廠函數(icecream 冰淇淋),這可以用來改變傳回物件的模型

function createIceCream(flavour='Vanilla') {
 return {
 type: 'icecream',
 scoops: 3,
 flavour
 }
 }
登入後複製

    理論上,您可以使用數百個參數的工廠函數來傳回非常特使的深層嵌套對象,但正如我們將看到的,這根本不是組合的精髓。

    2.組合好的工廠函數

    在一個工廠函數中定義另一個工廠函數,可以幫助我們把複雜的工廠函數分割成較小的,可重用的碎片。

    例如,我們可以建立一個 dessert(甜點)工廠函數,透過前面的 jelly(果凍)和 icecream(冰淇淋)工廠函數來定義。    

 function createDessert() {
 return {
 type: 'dessert',
 bowl: [
 createJelly(),
 createIceCream()
 ]
 };
 }
登入後複製

    我們可以組合工廠函數來建立任何複雜的對象,這不需要我們結合使用 new 或 this 。物件可以用 has-a (具有) 關係而不是 is-a (是) 來表示。也就是說,可以用組合而不是繼承來實現。    

    例如,使用繼承。

 // A trifle *is a* dessert 蛋糕*是*甜点
 function Trifle() {
 Dessert.apply(this, arguments);
 }
 Trifle.prototype = Dessert.prototype;
 // 或者
 class Trifle extends Dessert {
 constructor() {
 super();
 }
 }
登入後複製

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

 // 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.非同步的工廠函數

#    並非所有工廠都會立即回傳資料。例如,有些必須先取得數據。在這些情況下,我們可以傳回 Promises 來定義工廠函數。  

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

    這種深度嵌套的縮排會使非同步工廠難以閱讀和測試。將它們分解成多個不同的工廠通常是有幫助的,可以使用如下編寫。

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

    當然,我們可以使用回呼函數,但我們已經有了像 Promise.all 這樣的工具回傳 Promises 來定義工廠函數。    

 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 作為命名約定來顯示這些工廠做一些非同步工作和回到promise。

4.函数和方法

到目前为止,我们还没有看到任何工厂用方法返回对象,这是故意的。这是因为一般来说,我们不需要这么做。工厂允许我们从计算中分离我们的数据。这意味着我们总是能够将对象序列化为JSON,这对于在会话之间持久化,通过HTTP或WebSockets发送它们,并将它们放入数据存储很重要。

例如,不是在 jelly(果冻) 对象上定义 eat 方法,我们可以定义一个新的函数,它接受一个对象作为参数并返回一个修改的版本。

function eatJelly(jelly) {
 if(jelly.scoops > 0) {
 jelly.scoops -= 1;
 }
 return jelly;
 }
登入後複製

一点点句法帮助使这是一个可行的模式,那些喜欢编程而不改变数据结构的人。对于那些喜欢编程而不改变数据结构的人来说,使用 ES6 的 ... 语法 是一个可行的模式。

 function eat(jelly) {
 if(jelly.scoops > 0) {
 return { ...jelly, scoops: jelly.scoops - 1 };
 } else {
 return jelly;
 }
 }
登入後複製

现在,不是这样写:

 import { createJelly } from './jelly';
 createJelly().eat();
登入後複製

而是这样写

 import { createJelly, eatJelly } from './jelly';
 eatJelly(createJelly());
登入後複製

最终结果是一个函数,它接受一个对象并返回一个对象。我们称之为返回对象的函数是什么? 一个工厂!

5.高级工厂

将工厂传递给 高阶函数 ,这将给我们带来巨大的控制力。例如,我们可以使用这个概念来创建一个增强的对象。

 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
 };
 });
登入後複製

这个增强的对象采用一个现有工厂,并将其包装以创建返回带有时间戳实例的工厂。或者,如果我们想要确保一个工厂返回不可变的对象,我们可以用 freezer 来增强它。

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

    6.结论

    作为一个 聪明的程序员 曾经说过:从没有抽象比错误的抽象更容易回收。JavaScript项目有一个趋势,变得难以测试和重构,因为我们经常鼓励使用复杂的抽象层。原型和类实现一个简单的想法使用复杂和不人性的工具,如 new 和 this ,即使现在,这仍然引起 各种各样的困惑 -几年后他们被添加到语言。对象和函数对于来自大多数语言背景的程序员来说是有意义的,并且都是JavaScript中的原始类型,所以可以说工厂不是抽象的!对象和函数对来自大多数背景的程序员都有意义,并且都是JavaScript中的原始类型,所以可以说工厂不是抽象的!使用这些简单的构建块使得我们的代码对于没有经验的程序员更加友好,这绝对是我们应该关心的事情。工厂鼓励我们用原始数据来模拟复杂和异步数据,原始数据具有组合的自然能力,而不强迫我们去做一些高级抽象。 当我们坚持简单时,JavaScript更甜蜜!

以上是詳解JavaScript中的工廠函數的範例程式碼的詳細內容。更多資訊請關注PHP中文網其他相關文章!

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

如何使用WebSocket和JavaScript實現線上語音辨識系統 如何使用WebSocket和JavaScript實現線上語音辨識系統 Dec 17, 2023 pm 02:54 PM

如何使用WebSocket和JavaScript實現線上語音辨識系統引言:隨著科技的不斷發展,語音辨識技術已成為了人工智慧領域的重要組成部分。而基於WebSocket和JavaScript實現的線上語音辨識系統,具備了低延遲、即時性和跨平台的特點,成為了廣泛應用的解決方案。本文將介紹如何使用WebSocket和JavaScript來實現線上語音辨識系

WebSocket與JavaScript:實現即時監控系統的關鍵技術 WebSocket與JavaScript:實現即時監控系統的關鍵技術 Dec 17, 2023 pm 05:30 PM

WebSocket與JavaScript:實現即時監控系統的關鍵技術引言:隨著互聯網技術的快速發展,即時監控系統在各個領域中得到了廣泛的應用。而實現即時監控的關鍵技術之一就是WebSocket與JavaScript的結合使用。本文將介紹WebSocket與JavaScript在即時監控系統中的應用,並給出程式碼範例,詳細解釋其實作原理。一、WebSocket技

如何利用JavaScript和WebSocket實現即時線上點餐系統 如何利用JavaScript和WebSocket實現即時線上點餐系統 Dec 17, 2023 pm 12:09 PM

如何利用JavaScript和WebSocket實現即時線上點餐系統介紹:隨著網路的普及和技術的進步,越來越多的餐廳開始提供線上點餐服務。為了實現即時線上點餐系統,我們可以利用JavaScript和WebSocket技術。 WebSocket是一種基於TCP協定的全雙工通訊協議,可實現客戶端與伺服器的即時雙向通訊。在即時線上點餐系統中,當使用者選擇菜餚並下訂單

如何使用WebSocket和JavaScript實現線上預約系統 如何使用WebSocket和JavaScript實現線上預約系統 Dec 17, 2023 am 09:39 AM

如何使用WebSocket和JavaScript實現線上預約系統在當今數位化的時代,越來越多的業務和服務都需要提供線上預約功能。而實現一個高效、即時的線上預約系統是至關重要的。本文將介紹如何使用WebSocket和JavaScript來實作一個線上預約系統,並提供具體的程式碼範例。一、什麼是WebSocketWebSocket是一種在單一TCP連線上進行全雙工

JavaScript與WebSocket:打造高效率的即時天氣預報系統 JavaScript與WebSocket:打造高效率的即時天氣預報系統 Dec 17, 2023 pm 05:13 PM

JavaScript和WebSocket:打造高效的即時天氣預報系統引言:如今,天氣預報的準確性對於日常生活以及決策制定具有重要意義。隨著技術的發展,我們可以透過即時獲取天氣數據來提供更準確可靠的天氣預報。在本文中,我們將學習如何使用JavaScript和WebSocket技術,來建立一個高效的即時天氣預報系統。本文將透過具體的程式碼範例來展示實現的過程。 We

簡易JavaScript教學:取得HTTP狀態碼的方法 簡易JavaScript教學:取得HTTP狀態碼的方法 Jan 05, 2024 pm 06:08 PM

JavaScript教學:如何取得HTTP狀態碼,需要具體程式碼範例前言:在Web開發中,經常會涉及到與伺服器進行資料互動的場景。在與伺服器進行通訊時,我們經常需要取得傳回的HTTP狀態碼來判斷操作是否成功,並根據不同的狀態碼來進行對應的處理。本篇文章將教你如何使用JavaScript來取得HTTP狀態碼,並提供一些實用的程式碼範例。使用XMLHttpRequest

javascript如何使用insertBefore javascript如何使用insertBefore Nov 24, 2023 am 11:56 AM

用法:在JavaScript中,insertBefore()方法用於在DOM樹中插入一個新的節點。這個方法需要兩個參數:要插入的新節點和參考節點(即新節點將要插入的位置的節點)。

JavaScript與WebSocket:打造高效率的即時影像處理系統 JavaScript與WebSocket:打造高效率的即時影像處理系統 Dec 17, 2023 am 08:41 AM

JavaScript是一種廣泛應用於Web開發的程式語言,而WebSocket則是一種用於即時通訊的網路協定。結合二者的強大功能,我們可以打造一個高效率的即時影像處理系統。本文將介紹如何利用JavaScript和WebSocket來實作這個系統,並提供具體的程式碼範例。首先,我們需要明確指出即時影像處理系統的需求和目標。假設我們有一個攝影機設備,可以擷取即時的影像數

See all articles