我正在阅读this article关于尝试在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();
有了这个:
function RabbitFactory() {
var rabbit = {
speed: 3
};
Object.setPrototypeOf(rabbit, {
getSpeed: function() {
return this.speed;
}
})
return rabbit;
}
var rabbit = RabbitFactory();
答案 0 :(得分: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();
我不确定有多少专业人士只使用工厂来创建对象,但我可能会挑出一个。正如文章中提到的,如果我们引用非常着名的“Design Patterns”,那么我们应该更喜欢对象组合而不是类继承。我完全赞同这个假设,因此回到JS和ES6类,我们可以说原型委托可能在某些情况下比继承更好。
但是,我们也不应该忘记这一点(正如文章中所提到的)声明:“它的实施方式并不重要根本,除非它实施得不好”。我想说,这个是一个非常好的。
答案 1 :(得分:3)
我不喜欢这些答案,因为他们使用this
关键字。你可以完全避免这种情况,仍然使用这样的工厂函数:
function createRabbit() {
var speed = 3;
return {
getSpeed: function() {
return speed;
}
}
}
var rabbit = createRabbit();
console.log(rabbit.getSpeed());
这家伙有一篇很好的文章:http://radar.oreilly.com/2014/03/javascript-without-the-this.html
答案 2 :(得分:1)
不,那是错的。您不应该使用Object.setPrototypeOf
,更好地使用Object.create
(尽管结果没有区别)。如果你每次都从一个对象文字创建原型,它就失去了它的所有共享优势,所以你应该完全放弃它或者将它移到函数之外以使它成为静态的。编写工厂函数的正确方法是
const protoRabbit = {
getSpeed: function() {
return this.speed;
}
};
function createRabbit() {
var rabbit = Object.create(protoRabbit);
rabbit.speed = 3;
return rabbit;
}
var rabbit = createRabbit();
答案 3 :(得分:1)
最简单的模式是:
function RabbitFactory() {
return {
speed: 3,
getSpeed() { return this.speed; }
};
}
var rabbit = RabbitFactory();
答案 4 :(得分:1)
尽管问题的名称与工厂功能有关,但这里的许多答案都建议使用Constructor Functions。
工厂函数如下所示:
const RabbitFactory = () => {
const speed = 3;
const GetSpeed = () => speed;
return { GetSpeed }
}
const rabbit = RabbitFactory();
rabbit.GetSpeed() // -> 3
rabbit.speed // -> undefined!
我更喜欢Factory函数而不是构造函数,原因是:
Object
构造函数GetSpeed
吸气剂)答案 5 :(得分:0)
这篇文章听起来像道格拉斯·克罗克福德演讲。无论如何,它提到了这种模式。
function RabbitFactory(){
rabbit = Object.create({ getSpeed: function() {
return this.speed;
}
});
rabbit.speed = 3;
return rabbit;
}
ES6中引入了 setPrototypeOf
/ getPrototypeOf
或__proto__
属性,而Object.create()
是ES5功能。 setPrototypeOf
/ getPrototypeOf
或__proto__
适用于子类,但不应与Object.create()
一起使用
我会继续使用构造函数。