类和构造函数与工厂函数的澄清需求

时间:2017-01-15 08:45:12

标签: javascript ecmascript-6

我正在玩ES6课程,我最终的目标是了解类与构造函数和工厂函数之间的区别。我的当前理解是构造函数和类基本上使用相同的设计模式,类只是构造函数的新语法。基于这个假设,我试图创建一些示例来显示类/构造函数和工厂函数之间的对比。

通过下面的示例,我的目标是返回新对象和一些继承的方法。

我的第一个例子是类语法相当简单。

示例#1:

class Person {
    constructor(name, age, location, occupation) {
        this.name = name;
        this.age = age;
        this.location = location;
        this.occupation = occupation;
    }
    printDescription() {
        console.log(`My name is ${this.name} and I'm ${this.age} years old. I live in ${this.location} and I work as a ${this.occupation}.`);
    }
}
const firstUser = new Person('Tom', 30, 'Sydney', 'Teacher');
firstUser.printDescription();

在第二个例子中,我试图用不同的方法复制第一个例子,但我不确定这是工厂构造函数还是工厂函数。

示例#2:

function PersonMaker (name, age, location, occupation) {

    let person = {name, age, location, occupation};

    person.printDetails = () => {
        console.log(`My name is ${name} and I'm ${age} years old. I live in ${location} and I work as a ${occupation}.`);
    };

    return person;
}

const secondUser = PersonMaker('Johnny', 25, 'London', 'Driver');
secondUser.printDetails();

我需要澄清第二个例子中使用的模式,如果它不是工厂函数,我怎么把它变成一个?

3 个答案:

答案 0 :(得分:3)

因为它返回一个对象,它是一个工厂函数 - it's already explained there

Constuctor函数行为与此不同,它不返回值:

function Person(name, age, location, occupation){
    this.name = name
    this.age = age
    this.location = location
    this.occupation = occupation
}

Person.prototype.printDetails = function(){
        console.log(`My name is ${this.name} and I'm ${this.age} years old. I live in ${this.location} and I work as a ${this.occupation}.`);
};

const secondUser = new Person('Johnny', 25, 'London', 'Driver');
secondUser.printDetails();

我通过将原型扩展到单独的构造函数来使用方法的定义,你仍然可以在构造函数中定义一个方法:

function Person(name, age, location, occupation){
    this.name = name
    this.age = age
    this.location = location
    this.occupation = occupation

    this.printDetails = function(){
        console.log(`My name is ${this.name} and I'm ${this.age} years old. I live in ${this.location} and I work as a ${this.occupation}.`);
    };
}

const secondUser = new Person('Johnny', 25, 'London', 'Driver');
secondUser.printDetails();

答案 1 :(得分:3)

为避免传递多个参数,您可以这样做。

const PersonMaker = description => {
  const {name, age, location, occupation} = description;
  return {
    printDetails: () => {
      console.log(
        `My name is ${name} and I'm ${age} years old. I live in ${location} and I work as a ${occupation}.`,
      );
    },
  };
};

const secondUser = PersonMaker({
  name: 'Johnny',
  age: '25',
  location: 'London',
  occupation: 'Driver',
});


console.log(secondUser.printDetails());

答案 2 :(得分:1)

Javascript的根源在于Prototypal Inheritance:

// Prototype
var ProtoCtr = function ProtoCtr(name, age) {
    this.name = name;
    this.age = age;
};
ProtoCtr.prototype.printDetails = function printDetails() { console.log(`Hi, I'm ${this.name} and I'm ${this.age} years old`); };

var protoInstance = new ProtoCtr('John', 21);
protoInstance.printDetails();

简而言之:

  • 函数公开原型

  • 定义引用实例的this上下文

  • 使用new关键字创建实例

然后,使用ES6,该语言提供了使用class关键字的可能性(以取悦古典OO开发人员)。它是一种语法,允许在块中对对象的声明进行分组,从而避免“手动”扩展原型。在引擎盖下,它与原型模型完全相同,它只是另一种写它的方式。

// Class
class ClassCtr {
    constructor(name, age) {
        this.name = name;
        this.age = age;
    }
    printDetails() {
        console.log(`Hi, I'm ${this.name} and I'm ${this.age} years old`);
    }
}
var classInstance = new ClassCtr('John', 21);
classInstance.printDetails();

关键概念大致相同,但您不使用原型向您的实例公开方法,而是直接在class块中声明它。

然后,有工厂模式,这不是语言规范,而是模式,是一种做事的方式。这是我个人的最爱。工厂函数构建并返回实例。使用此方法,您可以删除new关键字,并且不再需要this来引用您的实例:

// Factory
var factoryCtr = function factoryCtr(name, age) {
    var instance = {
        name: name,
        age: age,
        printDetails: function printDetails() { console.log(`Hi, I'm ${instance.name} and I'm ${instance.age} years old`); }
    };
    return instance;
}
var factoryInstance = factoryCtr('John', 21);
factoryInstance.printDetails();

即使本次演讲不涵盖课程,我建议您观看此视频: https://www.youtube.com/watch?v=ya4UHuXNygM

我希望这有助于:)