如何将方法从某个类的实例复制到对象

时间:2016-06-17 16:29:24

标签: javascript oop inheritance

给定课程

class Test {
  test() {
     console.log('test called');
  }
}

还有一些对象toExtend = {}

如何扩展此对象以使其具有test方法?

Object.assign(以及_.extend_.assign$.extend)不会复制方法。什么是最好的方法呢?

请注意toExtend从外部传递

UPD: toExtend是另一个类的实例,并拥有自己的原型方法

1 个答案:

答案 0 :(得分:9)

对象文字

对于以自己的原型(Object.getPrototypeOf(toExtend) === Object.protoype))开头的对象文字,您只需使用Object.setPrototypeOf来扩展对象:



class Test {
  test() {
    console.log('test called');
  }
}

const toExtend = {};

// Set the prototype, so you "inherit" methods:
Object.setPrototypeOf(toExtend, Test.prototype);
toExtend.test();




在较旧的运行时中,您必须手动分配原型:



function Test() {
  // noop ctor
}

Test.prototype.test = function() {
  console.log('test called');
};


var toExtend = {};

// Set the prototype, so you "inherit" methods:
toExtend.__proto__ = Test.prototype;
toExtend.test();




班级实例

对于现有类的实例,事情要复杂得多。他们确实拥有自己的原型,可能具有必须复制的属性,因此您需要完成这些:



class Foo {
  test() {
    console.log('test');
  }
}

class Bar {
  toast() {
    console.log('toast');
  }
}

function dynamicExtend(target, base) {
  const baseProto = Object.getPrototypeOf(target);
  if (baseProto == Object.prototype) {
    // simple case: no existing prototype
    Object.setPrototypeOf(target, base.prototype);
  } else {
    // complex case: existing prototype
    const proxyClass = class extends base {};
    const proxyProto = proxyClass.prototype;

    // assign the target properties
    Object.getOwnPropertyNames(baseProto).forEach(n => {
      const desc = Object.getOwnPropertyDescriptor(baseProto, n);
      Object.defineProperty(proxyProto, n, desc);
    });

    Object.setPrototypeOf(target, proxyProto);
  }
}

const targets = [{},
  new Bar()
];

targets.forEach(t => {
  dynamicExtend(t, Foo);
  t.test();
  if (t.toast) {
    t.toast();
  }
});




请注意,由于代理类,这会破坏instanceof样式继承检查。

__proto__

在评论{@ 3}}中为@PatrickRoberts noted,因此您应尽可能选择setPrototypeOf