简体   繁体   English

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

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

I've watched the video from this question on class-free OOP several times now, and I'm having trouble applying this to a real world example. 我现在已经多次在无类OOP上观看了这个问题的视频,而我在将这个应用到现实世界的例子中时遇到了麻烦。

Crockford's new constructor pattern looks like this: Crockford的新构造函数模式如下所示:

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

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

Where spec is an options hash and the resulting object exposes methods which close over all of the internal members. 其中spec是一个选项哈希,结果对象公开了关闭所有内部成员的方法。 Ignoring the destructuring (as this can be done in long-form in present-day JS,) how do I apply this pattern in a real world example? 忽略解构(因为这可以在现今的JS中以长篇形式完成) ,我如何在现实世界的例子中应用这种模式?

I currently have a library with a base class Module(model, id) where model is some bootstrapping data. 我目前有一个带有基类Module(model, id)的库,其中model是一些引导数据。

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

I then have several flavors of modules which inherit from this parent Module . 然后我有几种类型的模块继承自这个父Module Under Crockford's pattern, I would instead have this as a "constructor": 在Crockford的模式下,我会把它作为“构造函数”:

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

    return Object.freeze({});
}

How do I use Crockford's pattern (which doesn't seem to use inheritance at all, but rather composing an object from multiple sources) to share this basic construction among multiple flavors of modules ? 我如何使用Crockford的模式(它似乎根本不使用继承,而是从多个源组成一个对象) 在多种模块之间共享这种基本结构

I know that id and model will become local variables in the "constructor" of each module; 我知道idmodel将成为每个模块的“构造函数”中的局部变量; I am essentially asking how to avoid repeating model = spec.model for each flavor of module using Crockford's pattern. 我基本上问如何避免使用Crockford模式为每种模块重复model = spec.model

What Crockford calls “class-free inheritance” is actually still prototypal inheritance. Crockford所说的“无类继承”实际上仍然是原型继承。 Actually, there are two types of prototypal inheritance mechanisms: 实际上,有两种 类型的原型继承机制:

  1. Prototypal inheritance via delegation (aka differential inheritance). 通过委托(又称差异继承)进行原型继承。
  2. Prototypal inheritance via cloning (aka concatenative inheritance). 通过克隆(aka连接继承)进行原型继承。

An example of differential prototypal inheritance 差异原型继承的一个例子

This is how I traditionally write object-oriented JavaScript code: 这就是我传统上编写面向对象的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> 

An example of concatenative prototypal inheritance 连接原型继承的一个例子

This is how Crockford advocates to write object-oriented JavaScript code: 这就是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> 

Better concatenative prototypal inheritance using mixins 使用mixins更好的连锁原型继承

Crockford's method of concatenative prototypal inheritance has a lot of repetition. Crockford的连接原型继承方法有很多重复。 An alternative is: 另一种选择是:

 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> 

Using mixins without this 没有this使用mixins

Yes, you can use mixins without using this . 是的,你可以使用mixins而不使用this However, I don't see why you would want to: 但是,我不明白你为什么要这样做:

 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> 

Advantages of concatenative inheritance 连接继承的优点

There are many reasons to prefer composition over inheritance : 有很多理由喜欢组合而不是继承

  1. Simple multiple inheritance. 简单的多重继承。
  2. Faster property access. 更快的财产访问。

The only disadvantage that I can think of is that if the prototype is modified then the change will not be reflected on its instances. 我能想到的唯一缺点是,如果原型被修改,那么更改将不会反映在其实例上。 However, there's no good reason to change the prototype anyway. 但是,无论如何都没有充分的理由改变原型。 Hence, my mixins are all frozen. 因此,我的mixins都被冷冻了。

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

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