飞码网-免费源码博客分享网站

点击这里给我发消息

快速提示:什么是JavaScript中的工厂函数|-JavaScript教程

飞码网-免费源码博客分享网站 爱上飞码网—https://www.codefrees.com— 飞码网-matlab-python-C++ 爱上飞码网—https://www.codefrees.com— 飞码网-免费源码博客分享网站

作为JavaScript程序员,如果不了解函数和对象,您将无所不能。当它们一起使用时,它们便是我们开始使用称为组合的强大对象范式所需要的构建基块。今天,我们将介绍一些使用工厂函数来构成函数,对象和promise的惯用模式。

当一个函数返回一个对象时,我们称它为工厂函数

让我们看一个简单的例子。

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

每次我们调用该工厂时,它将返回一个果冻对象的新实例。

重要的是要注意,我们不必在工厂名称前加上前缀,create但可以使其他人更清楚该功能的意图。type属性也是如此,但通常可以帮助我们区分流经程序的对象。

参数化工厂功能

像所有函数一样,我们可以使用更改返回对象形状的参数定义工厂。

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

从理论上讲,您可以使用带有数百个参数的参数化工厂来返回非常具体且深度嵌套的对象,但是正如我们将看到的那样,这根本不符合组合的精神。

可组合的工厂功能

用一个工厂定义另一个工厂可以帮助我们将复杂的工厂分解成较小的,可重复使用的片段。

例如,我们可以创建一个甜点工厂,该工厂根据之前的果冻和冰淇淋工厂来定义。

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;

// or

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()
  };
}

异步工厂功能

并非所有工厂都准备好立即返回数据。例如,有些将必须首先获取数据。

在这种情况下,我们可以定义返回承诺的工厂。

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构成返回promise的工厂之工具

 
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作为一种命名约定来表明这些工厂进行一些异步工作并返回诺言。

功能与方法

到目前为止,我们还没有看到任何使用方法返回对象的工厂,这是有意为之的。这是因为一般而言,我们不需要

工厂使我们能够将数据与计算分开。

这意味着我们将始终能够将对象序列化为JSON,这对于在会话之间持久化它们,通过HTTP或WebSockets发送它们并将它们放入数据存储区而言非常重要。

例如,我们无需定义在果冻对象上的eat方法,而只需定义一个新函数即可将对象作为参数并返回修改后的版本。

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

语法上的一点点帮助使该模式成为那些希望在不更改数据结构的情况下进行编程的人的可行模式。

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());

最终结果是一个函数,该函数接受一个对象并返回一个对象。

我们怎么称呼返回对象的函数?一个工厂!

高阶工厂

作为高阶函数传递工厂给我们带来了巨大的控制权。例如,我们可以使用此概念来创建增强器

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!

结论

正如一个明智的程序员曾经说过的:

从无抽象中恢复要比错误的抽象容易得多。

由于经常鼓励我们构建复杂的抽象层,因此JavaScript项目倾向于难以测试和重构。

原型和类实现一个简单的想法与像复杂和不自然的工具new,并this仍然引起种种困惑,他们加入到语言即使是现在,年后。

对象和函数对于大多数背景的程序员来说都是有意义的,并且它们都是JavaScript中的原始类型,因此可以说工厂根本不是抽象的!

使用这些简单的构建块可使我们的代码对没有经验的程序员更加友好,这绝对是我们所有人都应该关注的事情。工厂鼓励我们使用具有自然合成能力的原语对复杂的异步数据进行建模,而不必强迫我们也无法进行高级抽象。当我们坚持简单性时,JavaScript会变得更甜美!

飞码网-免费源码博客分享网站 爱上飞码网—https://www.codefrees.com— 飞码网-matlab-python-C++ 爱上飞码网—https://www.codefrees.com— 飞码网-免费源码博客分享网站
赞 ()

相关推荐

内容页底部广告位3
留言与评论(共有 0 条评论)
   
验证码: