繁体   English   中英

如何在Crockford的新构造函数模式中共享“构造函数”功能?

[英]How do I share “constructor” functionality in Crockford's new constructor pattern?

我现在已经多次在无类OOP上观看了这个问题的视频,而我在将这个应用到现实世界的例子中时遇到了麻烦。

Crockford的新构造函数模式如下所示:

function constructor(spec) {
  let {member} = spec,
      {other}  = other_constructor(spec),
      method   = function () {
        // accesses member, other, method, spec
      };

  return Object.freeze({
      method,
      other,
  });
}

其中spec是一个选项哈希,结果对象公开了关闭所有内部成员的方法。 忽略解构(因为这可以在现今的JS中以长篇形式完成) ,我如何在现实世界的例子中应用这种模式?

我目前有一个带有基类Module(model, id)的库,其中model是一些引导数据。

// constructor, original flavor
function Module(model, id) {
  this.id = id;
  this.model = model;
}

然后我有几种类型的模块继承自这个父Module 在Crockford的模式下,我会把它作为“构造函数”:

// constructor, Crockford's Cool Ranch
function module(spec) {
    let id = spec.id,
        model = spec.model;

    return Object.freeze({});
}

我如何使用Crockford的模式(它似乎根本不使用继承,而是从多个源组成一个对象) 在多种模块之间共享这种基本结构

我知道idmodel将成为每个模块的“构造函数”中的局部变量; 我基本上问如何避免使用Crockford模式为每种模块重复model = spec.model

Crockford所说的“无类继承”实际上仍然是原型继承。 实际上,有两种 类型的原型继承机制:

  1. 通过委托(又称差异继承)进行原型继承。
  2. 通过克隆(aka连接继承)进行原型继承。

差异原型继承的一个例子

这就是我传统上编写面向对象的JavaScript代码的方法:

 var Aircraft = defclass({ constructor: function (model, speed) { this.model = model; this.speed = speed; }, describeAircraft: function () { alert("The " + this.model + " flies at " + this.speed + " speed."); } }); var FighterAircraft = extend(Aircraft, { constructor: function (model, speed, radar) { Aircraft.call(this, model, speed); this.radar = radar; }, describeFighterAircraft: function () { this.describeAircraft(); alert("It has a " + this.radar + " radar signature."); } }); var superFlanker = new FighterAircraft("Super Flanker", "Mach 2.25", "low"); superFlanker.describeFighterAircraft(); 
 <script> function defclass(prototype) { var constructor = prototype.constructor; constructor.prototype = prototype; return constructor; } function extend(constructor, properties) { var prototype = Object.create(constructor.prototype); for (var name in properties) prototype[name] = properties[name]; return defclass(prototype); } </script> 

连接原型继承的一个例子

这就是Crockford倡导编写面向对象的JavaScript代码的方式:

 var superFlanker = FighterAircraft({ model: "Super Flanker", speed: "Mach 2.25", radar: "low" }); superFlanker.describeFighterAircraft(); 
 <script> function Aircraft(spec) { var model = spec.model; var speed = spec.speed; function describeAircraft() { alert("The " + model + " flies at " + speed + " speed."); } return Object.freeze({ model: model, speed: speed, describeAircraft: describeAircraft }); } function FighterAircraft(spec) { var aircraft = Aircraft(spec); var model = spec.model; var speed = spec.speed; var radar = spec.radar; function describeFighterAircraft() { aircraft.describeAircraft(); alert("It has a " + radar + " radar signature."); } return Object.freeze({ model: model, speed: speed, radar: radar, describeFighterAircraft: describeFighterAircraft }); } </script> 

使用mixins更好的连锁原型继承

Crockford的连接原型继承方法有很多重复。 另一种选择是:

 var aircraft = mixin({ describeAircraft: function () { alert("The " + this.model + " flies at " + this.speed + " speed."); } }); var fighterAircraft = mixin(aircraft, { describeFighterAircraft: function () { this.describeAircraft(); alert("It has a " + this.radar + " radar signature."); } }); var superFlanker = fighterAircraft({ model: "Super Flanker", speed: "Mach 2.25", radar: "low" }); superFlanker.describeFighterAircraft(); 
 <script> function mixin() { var length = arguments.length; var index = 0; while (index < length) { var properties = arguments[index++]; for (var name in properties) constructor[name] = properties[name]; } return Object.freeze(constructor); function constructor(object) { for (var name in constructor) object[name] = constructor[name]; return Object.freeze(object); } } </script> 

没有this使用mixins

是的,你可以使用mixins而不使用this 但是,我不明白你为什么要这样做:

 var aircraft = mixin({ describeAircraft: function (aircraft) { alert("The " + aircraft.model + " flies at " + aircraft.speed + " speed."); } }); var fighterAircraft = mixin(aircraft, { describeFighterAircraft: function (fighterAircraft) { fighterAircraft.describeAircraft(); alert("It has a " + fighterAircraft.radar + " radar signature."); } }); var superFlanker = fighterAircraft({ model: "Super Flanker", speed: "Mach 2.25", radar: "low" }); superFlanker.describeFighterAircraft(); 
 <script> function mixin() { var length = arguments.length; var index = 0; while (index < length) { var properties = arguments[index++]; for (var name in properties) constructor[name] = properties[name]; } return Object.freeze(constructor); function constructor(object) { for (var name in constructor) { var value = constructor[name]; object[name] = typeof value === "function" ? value.bind(null, object) : value; } return Object.freeze(object); } } </script> 

连接继承的优点

有很多理由喜欢组合而不是继承

  1. 简单的多重继承。
  2. 更快的财产访问。

我能想到的唯一缺点是,如果原型被修改,那么更改将不会反映在其实例上。 但是,无论如何都没有充分的理由改变原型。 因此,我的mixins都被冷冻了。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM