javascript中的特征

Tin*_*nku 17 javascript prototype traits

如何在javascript中实现特征?

Tho*_*ing 17

function Trait (methods) {
  this.traits = [methods];
};

Trait.prototype = {
    constructor: Trait

  , uses: function (trait) {
      this.traits = this.traits.concat (trait.traits);
      return this;
    }

  , useBy: function (obj) {
      for (var i = 0; i < this.traits.length; ++i) {
        var methods = this.traits [i];
        for (var prop in methods) {
          if (methods.hasOwnProperty (prop)) {
            obj [prop] = obj [prop] || methods [prop];
          }
        }
      }
    }
};

Trait.unimplemented = function (obj, traitName) {
  if (obj === undefined || traitName === undefined) {
    throw new Error ("Unimplemented trait property.");
  }
  throw new Error (traitName + " is not implemented for " + obj);
};
Run Code Online (Sandbox Code Playgroud)

例:

var TEq = new Trait ({
    equalTo: function (x) {
      Trait.unimplemented (this, "equalTo");
    }

  , notEqualTo: function (x) {
      return !this.equalTo (x);
    }
});

var TOrd = new Trait ({
    lessThan: function (x) {
      Trait.unimplemented (this, "lessThan");
    }

  , greaterThan: function (x) {
      return !this.lessThanOrEqualTo (x);
    }

  , lessThanOrEqualTo: function (x) {
      return this.lessThan (x) || this.equalTo (x);
    }

  , greaterThanOrEqualTo: function (x) {
      return !this.lessThan (x);
    }
}).uses (TEq);


function Rational (numerator, denominator) {
  if (denominator < 0) {
    numerator *= -1;
    denominator *= -1;
  }
  this.numerator = numerator;
  this.denominator = denominator;
}

Rational.prototype = {
    constructor: Rational

  , equalTo: function (q) {
      return this.numerator * q.numerator === this.denominator * q.denominator;
    }

  , lessThan: function (q) {
      return this.numerator * q.denominator < q.numerator * this.denominator;
    }
};

TOrd.useBy (Rational.prototype);

var x = new Rational (1, 5);
var y = new Rational (1, 2);

[x.notEqualTo (y), x.lessThan (y)]; // [true, true]
Run Code Online (Sandbox Code Playgroud)

  • 遗憾的是没有逐行解释。 (3认同)

Pet*_*ger 5

有不同的方法,同时也有生产就绪的库。

\n\n

Mixin 是跨类层次结构的代码重用的最古老的形式。它们需要按线性顺序组成,因为 Mixin 的概念不涵盖/识别冲突解决功能。

\n\n

特征是代码重用的细粒度单元,也适用于类级别;但它们更加灵活,因为 Traits 必须提供用于组合、排除或别名方法的组合运算符。

\n\n

我确实建议阅读两篇论文,它们都涵盖了与库无关的基于纯函数的 Mixins / Traits / Talents 方法。

\n\n
    \n
  1. Angus Croll 于 2011 年 5 月对 JavaScript Mixins 的全新审视
  2. \n
  3. 从 2014 年 4 月开始,JavaScript 的众多才华横溢,用于推广面向角色的编程方法,例如 Traits 和 Mixins
  4. \n
\n\n

基于纯函数和委托的 mixin 机制与接下来的 2 个给定示例一样简单......

\n\n
var Enumerable_first = function () {\n  this.first = function () {\n    return this[0];\n  };\n};\nvar list = ["foo", "bar", "baz"];\n\nconsole.log("(typeof list.first)", (typeof list.first)); // "undefined"\n\nEnumerable_first.call(list); // explicit delegation\n\nconsole.log("list.first()", list.first()); // "foo"\n
Run Code Online (Sandbox Code Playgroud)\n\n

...第一个示例作用于“实例”级别,第二个示例覆盖“类”级别...

\n\n
var Enumerable_first_last = function () {\n  this.first = function () {\n    return this[0];\n  };\n  this.last = function () {\n    return this[this.length - 1];\n  };\n};\nconsole.log("(typeof list.first)", (typeof list.first));  // "function"   // as expected\nconsole.log("(typeof list.last)", (typeof list.last));    // "undefined"  // of course\n\nEnumerable_first_last.call(Array.prototype);  // applying behavior to [Array.prototype]\n\nconsole.log("list.last()", list.last());      // "baz"  // due to delegation automatism\n
Run Code Online (Sandbox Code Playgroud)\n\n

如果需要已建立和/或生产就绪的库,则应该仔细查看

\n\n
    \n
  1. 特征.js
  2. \n
  3. 鸡尾酒JS
  4. \n
\n\n

这么久

\n\n

附录一

\n\n

另请参阅:

\n\n\n\n

附录二

\n\n

因为我有时显然在摆弄这件事,所以我不想添加一些最后的想法......

\n\n

没有太多粘合代码(如上所述)的与库无关的方法仅适用于行为重用的非常细粒度的可组合单元。因此,只要不遇到超过 1 或 2 个容易解决的冲突,基于 Angus Croll 的Flight Mixins 等的模式就是可遵循的路径。

\n\n

如果涉及到真实的特征,就必须有一个抽象层次。该层(例如作为某种语法糖提供,如 DSL)需要隐藏复杂性,例如从特征中组合特征或在特征应用时解决冲突(当特征的行为应用于对象/类型时) )。

\n\n

到目前为止,SO 有 3 个示例,从我的角度来看,它们准确地提供了 OP 所要求的 \xe2\x80\xa6

\n\n
\n

如何在 javascript 中实现特征?

\n
\n\n\n