JavaScript Factory Functions vs Constructor Functions vs Classes

JavaScript Factory Functions vs Constructor Functions vs Classes

Source: JavaScript Factory Functions vs Constructor Functions vs Classes

中英文对照:

  • Factory Functions:工厂函数
  • Constructor Functions:构造器函数
  • Classes:类

JavaScript 中的“工厂函数”与“构造器函数”以及“类”

以下代码分别展示出以上三种函数的创建方式

// class
class ClassCar {
	driver() {
		console.log('Vroom!');
	}
}

const car1 = new ClassCar();
console.log(car1.driver());

// construnctor
function ConstrunctorCar() {}

ConstrunctorCar.prototype.drive = function() {
	console.log('Vroom!');
}

const car2 = new ConstructorCar();
console.log(car2.driver());

// factory
const proto = {
	driver() {
		console.log('Vroom!');
	}
};

const factoryCar = () => Object.create(proto);

const car3 = factoryCar();
console.log(car3.driver());

在 JavaScript 中,任何函数都可以返回一个新对象。当它不是构造器函数或类,那么它被称为工厂函数。

ES6 中 的 class 实际上是构造器函数的一种语法糖,简而言之,我们可以认为 ES6 中的 class 与构造器函数是一样的。

工厂函数和构造器函数的区别

最大的也是唯一的区别是:构造器函数强制要求调用者使用 new 关键字;而工厂函数并不需要;

当使用 new 关键字后都发生了什么呢?

  1. 实例化一个新的实例对象,同时绑定 this 到构造器函数的内部;
  2. 绑定 isntance.__proto__Constructor.prototype
  3. 因为第 2 步带来的副作用,需要绑定 instance.__proto__.constructorConstrunctor
  4. 隐式返回 this,这个 this 指向 instance

也就是说工厂函数在第 2 步的时候所产生的副作用没有被自动修正,也就是 instance.__proto__.constructor 此时并未指向 Construnctor

构造器函数和类的优点

  • 大部分书都会教你用这种方法;
  • this 指向/引用 新对象;
  • 人们习惯这种方式;

构造器函数和类的缺点

  • 需要使用 new 关键字。此点在当前的开发环境中已经不是问题了;
  • 实例化的细节被泄露到调用 API 中。这句不好理解,大体的意思是所有的调用者被构造器的实现所裹挟,也就是紧耦合状态。这种情况下非常不便于重构工作;
  • 违反了开闭原则。大体意思是随着项目的深入,最终都会走上将类重构成工厂的路,此时由于 JavaScript 的语言结构问题,以前调用类的客户端均使用了 new 关键字,这导致无法将类重构成工厂,会带来很多麻烦。个人理解,不违反开闭原则最好的办法是使用 interface,即面向接口编程,但由于 JavaScript 采用的是对象原型继承方式,并没有类这个概念,因此也就没有 interface 的概念,不过利用工厂函数可以变相的实现 interface 比如:
const Interface = (proto) => Object.create(proto)
/**
* 此时我们可以约定 proto 的 shape
* 比如:必须包含 a 属性,b 方法
* 再结合 typescript 可以实现编译器校验
*/
  • instanceOf 具有欺骗性。这是因为 instanceOf 本质是不是类型检测的方法,而是检测 instance.__proto__ 是否等于 Constructor.prototype
function foo() {}
const bar = {a: 'a'};

foo.prototype = bar;

console.log(bar instanceof foo); //false

const baz = Object.create(bar);

/**
* baz.__proto__ = bar
* foo.prototype = bar
* 因此 (baz instanceof foo) 返回 true
* 这是错误的
*/
console.log(baz instanceof foo); // true

使用工厂函数的优点

工厂函数比构造器函数和类更具备扩展性,它有很多更安全的代码重用机制。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值