代码之家  ›  专栏  ›  技术社区  ›  Florian

混合模式与原型构造器

  •  0
  • Florian  · 技术社区  · 6 年前

    我听说过 mixin pattern 昨天,我在尝试,但我对我认为的基本概念感到困惑。

    让我们关注这个函数:

    function applyMixins(derivedCtor: any, baseCtors: any[]) {
        baseCtors.forEach(baseCtor => {
            Object.getOwnPropertyNames(baseCtor.prototype).forEach(name => {
                derivedCtor.prototype[name] = baseCtor.prototype[name];
            });
        });
    }
    

    在基本构造函数原型迭代中,属性名之一是 constructor . 所以我们要做的是将derivedClass原型构造函数重新分配给最后一个基类原型构造函数。

    假设我们有三节课:

    class Disposable {
      public isDisposed: boolean;
      public dispose() {
        this.isDisposed = true;
      }
    }
    
    class Activable {
      public isActive: boolean;
      public activate() {
        this.isActive = true;
      }
      public deactivate(){
        this.isActive = false;
      }
    }
    
    class MyDisposableObject implements Disposable, Activable {
      //Disposable
      public isDisposed = false;
      public dispose: () => void;
    
      //Activable
      public isActive = false;
      public activate:() => void;
      public deactivate:() => void;
    }
    

    之后 applyMixins(MyDisposableObject, [Disposable, Activable]) 我们不再拥有MyDisposableObject实例的正确构造函数。

    const m = new MyDisposableObject();
    console.log(m.constructor); // output : f Activable() {}
    console.log(m instanceof MyDisposableObject) //output : true !?
    
    • 根据 MDN documentation , 构造函数属性返回对创建实例对象的对象构造函数的引用。 现在已经不是这样了因为 applyMixins 重新分配derivedClass.prototype.constructor。这不会导致副作用吗?

    var Disposable = /** @class */ (function () {
        function Disposable() {
        }
        Disposable.prototype.dispose = function () {
            this.isDisposed = true;
        };
        return Disposable;
    }());
    var Activable = /** @class */ (function () {
        function Activable() {
        }
        Activable.prototype.activate = function () {
            this.isActive = true;
        };
        Activable.prototype.deactivate = function () {
            this.isActive = false;
        };
        return Activable;
    }());
    var MyDisposableObject = /** @class */ (function () {
        function MyDisposableObject() {
            //Disposable
            this.isDisposed = false;
            //Activable
            this.isActive = false;
        }
        return MyDisposableObject;
    }());
    applyMixins(MyDisposableObject, [Disposable, Activable]);
    function applyMixins(derived, bases) {
        bases.forEach(function (base) {
            Object.getOwnPropertyNames(base.prototype).forEach(function (name) {
                derived.prototype[name] = base.prototype[name];
            });
        });
    }
    var m = new MyDisposableObject();
    console.log('m constructor :', m.constructor);
    console.log('m instanceof MyDisposableObject : ', m instanceof MyDisposableObject);

    编辑:

    我仍然不明白为什么文档示例重新分配 derivedClass.prototype原型 如果这是有害的或不好的,当我等待一个很好的解释时,我修改了Apple的IXIXIN,忽略了构造函数属性:

    function applyMixins(derived, bases) {
      bases.forEach((base) => {
        Object.getOwnPropertyNames(base.prototype)
        .filter((name) => name.toLowerCase() !== 'constructor')
        .forEach((name) => {
          derived.prototype[name] = base.prototype[name];
        })
      })
    }
    
    0 回复  |  直到 6 年前