什么是工厂函数和构造函数?

0 股票
0
0
0
0

介绍

要理解工厂函数和构造函数的概念,首先必须理解函数和对象。.

如果创建大量具有相似属性和功能的对象,代码会变得枯燥乏味且重复。我们应该牢记 DRY 原则,即“不要重复自己”。有一些函数式编程模式可以帮助我们编写更简洁、更高效的代码。工厂函数和构造函数都能胜任这项工作,但究竟应该使用哪一个呢?让我们深入了解一下工厂函数和构造函数的概念、功能和局限性,以及它们的异同。.

什么是工厂功能?

可以将工厂函数想象成一个真实的工厂,它接收原材料并快速生产多种产品。另一方面,工厂函数接收特定的输入,并利用这些输入来创建一个新对象。那么,这究竟对我们有什么用呢?我们可以单独创建每个对象,但这可能很耗时。如果您要创建具有相同属性但值不同的对象,那么创建工厂函数可以加快这个过程。.

const car1 = {
make: 'Toyota',
model: 'Tacoma',
year: 2018,
fuelType: 'gas', 
bodyType: 'mid-size pick-up truck',
getFullName() {
return `${this.year} ${this.make} ${this.model}`;
}
}
console.log(car1.getFullName()); // => 2018 Toyota Tacoma

在上面的例子中,我们创建了一个描述特定机器的对象。现在让我们创建一个与此类似的对象。.

const car2 = {
make: 'Tesla', 
model: 'Model S',
year: 2018,
fuelType: 'electric',
bodyType: 'sedan',
getFullName() {
return `${this.year} ${this.make} ${this.model}`;
}
}
console.log(car2.getFullName()); // => 2018 Tesla Model S 

现在,我可以继续讲解如何制造更多机器对象,但谁有时间这么做呢,对吧?让我们看看它作为工厂函数是如何运作的。.

function createCar (make, model, year, fuelType, bodyType) {
return {
make: make, 
model: model, 
year: year, 
fuelType: fuelType, 
bodyType: bodyType,
getFullName() {
return `${year} ${make} ${model}`;
}
}
}

现在我们有了一个可以为我们创建新对象的工厂函数。接下来,我们只需要传递数据,然后让工厂函数执行它的工作即可。.

function createCar (make, model, year, fuelType, bodyType) {
return {
make: make, 
model: model, 
year: year, 
fuelType: fuelType, 
bodyType: bodyType,
getFullName() {
return `${year} ${make} ${model}`;
}
}
}
const car1 = createCar('Toyota', 'Tacoma', 2018, 'gas', 'mid-size pick-up truck');
const car2 = createCar('Tesla', 'Model S', 2018, 'electric', 'sedan');
console.log(car1.getFullName()); // => 2018 Toyota Tacoma
console.log(car2.getFullName()); // => 2018 Tesla Model S

您可以使用工厂函数创建任意数量的对象,而无需重复编写代码。.

什么是构造函数?

构造函数是另一种 JavaScript 模式,它与工厂函数非常相似。然而,与工厂函数不同的是,构造函数实际上并不返回对象。要创建具有相同属性的不同对象,我们需要使用 `new` 关键字和 `this` 关键字。接下来,让我们通过可视化的方式了解构造函数是如何工作的。.

function Car(make, model, year, fuelType, bodyType) {
this.make = make
this.model = model 
this.year = year
this.fuelType = fuelType
this.bodyType = bodyType
this.getFullName = () => {
return `${this.year} ${this.make} ${this.model}`;
}
}

在上面的例子中,构造函数与工厂函数非常相似,区别在于构造函数使用了关键字“this”。”this”指的是创建实例对象的构造函数本身。换句话说,构造函数中的“this”没有实际值。你可以把它看作是新对象的基址。.

function Car(make, model, year, fuelType, bodyType) {
this.make = make
this.model = model 
this.year = year
this.fuelType = fuelType
this.bodyType = bodyType
this.getFullName = () => {
return `${this.year} ${this.make} ${this.model}`;
}
}
const car1 = new car('Toyota', 'Tacoma', 2018, 'gas', 'mid-size pick-up truck');
const car2 = new car('Tesla', 'Model S', 2018, 'electric', 'sedan');
console.log(car1.getFullName()); // => 2018 Toyota Tacoma
console.log(car2.getFullName()); // => 2018 Tesla Model S

要使用构造函数创建对象,我们需要使用另一个关键字“new”。在函数调用前使用“new”语句时,JavaScript 会自动执行两项操作:在函数内部,它会创建一个名为“this”的空对象;并将“this”对象返回给最初调用该函数的语句。.

function Car(make, model, year, fuelType, bodyType) {
// const this = {};
this.make = make
this.model = model 
this.year = year
this.fuelType = fuelType
this.bodyType = bodyType
this.getFullName = () => {
return `${this.year} ${this.make} ${this.model}`;
}
// return this;
}
const car1 = new car('Toyota', 'Tacoma', 2018, 'gas', 'mid-size pick-up truck');
const car2 = new car('Tesla', 'Model S', 2018, 'electric', 'sedan');
console.log(car1.getFullName()); // => 2018 Toyota Tacoma
console.log(car2.getFullName()); // => 2018 Tesla Model S

遗产

继承在工厂函数和建造者函数之间的区别中起着重要作用。.

function createCar (make, model, year, fuelType, bodyType) {
return {
make: make, 
model: model, 
year: year, 
fuelType: fuelType, 
bodyType: bodyType,
getFullName() {
return `${year} ${make} ${model}`;
}
}
}
const car1 = createCar('Toyota', 'Tacoma', 2018, 'gas', 'mid-size pick-up truck');
const car2 = createCar('Tesla', 'Model S', 2018, 'electric', 'sedan'); 
car1.getFullName = function() {
return `My ${fuelType} ${bodyType} is a ${year} ${make} ${model}`;
}
console.log(car1.getFullName()); // => My gas mid-size pick-up truck is a 2018 Toyota Tacoma
console.log(car2.getFullName()); // => 2018 Tesla Model S

让我们回到工厂函数的第一个例子。如果我们想重新声明 `car1.getFullName()` 函数会怎样?实际上,`car1.getFullName()` 和 `car2.getFullName()` 在内存中并不是同一个函数。每个对象都有自己专属的函数副本。这意味着,当函数创建一个对象并返回它时,它会复制对象的属性和值,并将它们绑定到调用该函数的每个对象上。.

function car(make, model, year, fuelType, bodyType) {
// const this = {};
this.make = make
this.model = model 
this.year = year
this.fuelType = fuelType
this.bodyType = bodyType
this.getFullName = () => {
return `${this.year} ${this.make} ${this.model}`;
}
// return this;
}
const car1 = new car('Toyota', 'Tacoma', 2018, 'gas', 'mid-size pick-up truck');
const car2 = new car('Tesla', 'Model S', 2018, 'electric', 'sedan');
console.log(car1); // => car {make: 'Toyota', model: 'Tacoma' , etc.}

现在我们来看一下上面的构造函数。构造函数创建时,它有自己的原型。当我们使用 `new` 关键字创建一个新的 `Car` 对象时,它会创建一个 `Car` 类型的实例。换句话说,`car1` 的原型是 `Car` 类型。`car1` 继承自 `Car` 构造函数。这允许我们向 `Car` 原型添加属性。.

Car.prototype.sentence = function() {
return `My ${this.fuelType} ${this.bodyType} is a ${this.year} ${this.make} ${this.model}`;
}
console.log(car1); // => Car {
// make: 'Toyota',
// model: 'Tacoma',
// year: 2018,
// fuelType: 'gas',
// bodyType: 'mid-size pick-up truck',
// getFullName: [Function (anonymous)]
// }

请注意,句子功能并非直接添加到汽车生成器本身中。.

console.log(Car.prototype); // => { sentence: [Function (anonymous)] }

但当我们查看其原型时,发现它确实存在!我们现在可以使用新增功能了。.

console.log(car1.sentence()); // => My gas mid-size pick-up truck is a 2018 Toyota Tacoma
console.log(car2.sentence()); // => My electric sedan is a 2018 Tesla Model S

现在我们了解了每种操作的工作原理,问题是:我们应该使用哪一种?两者都能得到相同的结果。当需要向继承自构造函数的任何对象添加或删除属性时,构造函数非常有用。然而,工厂函数更容易理解,因为它本质上就是一个函数。对于工厂函数,我们不需要引入“new”关键字。借助闭包,它可以更加灵活。有了闭包,我们可以实现所谓的“数据隐私”。让我们来看另一个例子来解释它是如何工作的。.

function createCar(make, model, year) {
return {
getFullName() {
return `${year} ${make} ${model}`;
}
}
}
const car1 = createCar('Toyota', 'Tacoma', 2018); 
console.log(car1.getFullName()); // => 2018 Toyota Tacoma
console.log(car1.make); // => undefined
console.log(car1); // => { getFullName: [Function: getFullName] }

结果

总而言之,自己编写代码的关键在于,这样做本身并没有什么错。保持代码简洁明了的好方法是:在最合适的情况下使用工厂函数和构造函数。.

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

您可能也喜欢