JavaScript:覆盖整个类

时间:2017-05-01 19:59:48

标签: javascript

我试图覆盖一个类的功能:

class MyClass {
  constructor() {
    // more code
  }

  myFunction = function() {
    console.log('not this')
  }
}

// can't change the code above

MyClass.prototype.myFunction = function() {
  console.log('it should print this')
}

new MyClass().myFunction()

但巴贝尔将上述内容汇总到此:

class MyClass {
  constructor() {
    // more code

    this.myFunction = function () {
      console.log('not this');
    };
  }
}

// can't change the code above

MyClass.prototype.myFunction = function () {
  console.log('it should print this');
};

new MyClass().myFunction();

因为函数被定义为原始代码中的属性,所以Babel将该定义放在构造函数中。 如果我理解正确原型只包含函数,而不是所有属性。 因为构造函数在对象来自原型之后运行,所以我无法使用原型来覆盖该函数。

我的第二次尝试是覆盖构造函数:

class MyClass {
  constructor() {
    // more code
  }

  myFunction = function () {
    console.log('not this')
  }
}

// can't change the code above

let oldConstructor = MyClass.prototype.constructor
MyClass.prototype.constructor = function() {
  // call old constructor first, it will set myFunction
  oldConstructor()

  // now overwrite myFunction
  this.myFunction = function () {
    console.log('it should print this')
  }
}

new MyClass().myFunction()

好吧,试试吧...... 使用Babel进行编译,将其保存到test.js并运行:

~> node test.js
not this

我尽量让问题变得一般。关于为什么我不能在特定情况下更改类的更多背景信息:该类实际上来自我使用的库,而我使用的其他包也依赖于该库。 MeteorJS需要包来指定其依赖项的确切版本和来源,这就是我不能使用fork的原因:我必须派生依赖于这个库的每个包。

4 个答案:

答案 0 :(得分:0)

事实上你正在改变你的课程,但是因为how javascript interpreter looks for information inside its objects而没有“取消”效果。首先是对象内部的属性,然后是原型链。

在您的第一个示例中,如果您“删除”本地属性,则更改生效。例如:

    class MyClass {
  constructor() {
    // more code

    this.myFunction = function () {
      console.log('not this');
    };
  }
}

// can't change the code above

MyClass.prototype.myFunction = function () {
  console.log('it should print this');
};

const obj = new MyClass();
delete obj.myFunction;
obj.myFunction();

https://jsbin.com/gixufadewu/edit?js,console

答案 1 :(得分:0)

这不可能。每当您实例化Hard Reload时,内部MyClass都会重新定义。但不是原型链中定义的myFunction。因此,Interpreter将首先在实例中查找方法,然后在原型链中查找。在原型链中定义myFunction,可以使用JavaScript inheritance覆盖。

例如:

methods

答案 2 :(得分:0)

由于原始问题没有解决方案,我最终使用了这个:

class MyClass {
  myFunction = function() {
    console.log('not this')
  }
}

class MyNewClass extends MyClass {
  myFunction = function() {
    console.log('should print this')
  }
}

new MyNewClass().myFunction()

显然我现在总是必须使用MyNewClass,这是我真正不想要的,原始问题要求提供覆盖现有Class功能的解决方案,但这在我的情况下有效。

答案 3 :(得分:0)

你可以做的是通过在原型上放置一个getter / setter来拦截任务:

function myFunction() {
  console.log('it should print this');
}
Object.defineProperty(MyClass.prototype, "myFunction", {
  set(val) { /* ignore */ },
  get() { return myFunction; }
});

或者,您可以decorate the constructor,但对于ES6类来说,这意味着extra precautions