如何使用工厂函数编写JavaScript

Max*_*kyi 5 javascript

我正在阅读这篇关于尝试在JavaScript中模仿OOP的危险的文章,其中包括以下内容:

在JavaScript中,工厂函数只是构造函数,减去了new需求,全局污染危险和尴尬的限制(包括恼人的初始大写字母约定).

JavaScript不需要构造函数,因为任何函数都可以返回一个新对象.通过动态对象扩展,对象文字和Object.create(),我们拥有我们需要的一切 - 没有任何混乱.并且this行为就像在任何其他功能中一样.欢呼!

我是否正确地假设给定这种方法我们应该替换此代码:

function Rabbit() {
    this.speed = 3;
}

Rabbit.prototype = {
    this.getSpeed = function() {
        return this.speed;
    }
}

var rabbit = new Rabbit();
Run Code Online (Sandbox Code Playgroud)

有了这个:

function RabbitFactory() {
    var rabbit = {
        speed: 3
    };

    Object.setPrototypeOf(rabbit, {
        getSpeed: function() {
            return this.speed;
        }
    })

    return rabbit;
}

var rabbit = RabbitFactory();
Run Code Online (Sandbox Code Playgroud)

Art*_*ich 6

基本上我会区分3种方法来在JS中创建一个对象:

  • 构造函数

这里有3个例子(考虑你的兔子的一个)

// class
class Rabbit {
  constructor() {
    this.speed = 3; 
    // it would be so nice to have just 'static const speed = 3;' instead of
    // using constructor for that
  }
  getSpeed() {
    return this.speed;
  }
}
let rabbit1 = new Rabbit();

// constructor
function ConstructorRabbit(){ }
ConstructorRabbit.prototype.speed = 3;
ConstructorRabbit.prototype.getSpeed = function() {
  return this.speed;
};
let rabbit2 = new ConstructorRabbit();

// factory
const rabbitProto = {
  speed: 3,
  getSpeed() {
    return this.speed;
  }
};
function factoryRabbit () {
  return Object.create(rabbitProto);
}
let rabbit3 = factoryRabbit();
Run Code Online (Sandbox Code Playgroud)

我不确定有那么多专业人士只使用工厂来创建对象,但我可能会挑出一个.正如文章中提到的,如果我们引用非常着名的" 设计模式 ",那么我们应该更喜欢对象组合而不是类继承.而且我完全赞同这个假设,因此回到JS和ES6类,我们可以说原型委托在某些情况下可能比类继承更好.

但是,我们也不应该忘记这一点(正如文章中所提到的)声明:"它的实施方式根本不重要,除非它的实施很差".我想说,这个是一个非常好的.


Tza*_*Leh 5

这里的许多答案都建议使用构造函数,尽管问题的名称与工厂函数有关

工厂函数如下所示:

const RabbitFactory = () => {
  const speed = 3;
  const GetSpeed = () => speed;
  return { GetSpeed }
}
const rabbit = RabbitFactory();
rabbit.GetSpeed() // -> 3
rabbit.speed // -> undefined!
Run Code Online (Sandbox Code Playgroud)

我更喜欢工厂函数而不是构造函数,因为:

  • 你不需要弄乱原型设计
  • 您不需要使用Object构造函数
  • 使您能够在工厂中选择私有和公开的内容
    (在我的示例中,速度是私有的,这是一个很好的做法。如果您想读取兔子速度的值,请使用GetSpeedgetter)


Ber*_*rgi 4

不,那是错误的。您不应该使用Object.setPrototypeOf,更好地使用Object.create(尽管它对结果没有影响)。如果每次都从对象字面量创建原型,它就会失去所有共享优势,因此您应该完全放弃它或将其移到函数之外以使其静态。编写工厂函数的正确\xe2\x84\xa2 方法是

\n\n
const protoRabbit = {\n    getSpeed: function() {\n        return this.speed;\n    }\n};\nfunction createRabbit() {\n    var rabbit = Object.create(protoRabbit);\n    rabbit.speed = 3;\n    return rabbit;\n}\n\nvar rabbit = createRabbit();\n
Run Code Online (Sandbox Code Playgroud)\n