javascript - 如何在运行时在此类中更改类的原型(prototype)(使用 ES6 类)

标签 javascript ecmascript-6

我有以下类“X”,我想动态地向它的原型(prototype)添加一些东西,就像这样(这有效):

    class X{
        someUnrelatedFunction(){};	
    }
    
    //adding some stuff at runtime, in real situation, the ['a','b','c'] aren't "known" in advance like here.

    ['a','b','c'].forEach(elem => {
    	X.prototype[elem] = () =>{
      	    console.log('called with : ' + elem);
      };
    })

    //tests:

    x = new X();
    x.c();//works, outputs 'called with : c';

但是class 声明本身。我想这样做,让事情更具可读性,即我希望“原型(prototype)”初始化属于类本身。

现在我正在“构造函数”中执行此操作,如下所示:

class X{
	constructor(){
  	//we don't want to do that again:
  	if(typeof X.prototype.inited === 'undefined'){
    	X.prototype.inited = true;
    	console.log('-constructor: initing prototype');
      ['a','b','c'].forEach(elem => {
        X.prototype[elem] = () =>{
          console.log('called with : ' + elem);
        };
      })      
  	}else{
    	console.log('-constructor: no need to re-init prototype');
    }	
  }
}


x1 = new X();
x1.a();

x2 = new X();
x2.b();

fiddle :https://jsfiddle.net/nypL29f3/4/

但这对我来说似乎很棘手,而且在类内部我实际上是在“外部”引用它,即我正在使用“X”。如果我更改了类名,我也需要更改那部分代码。

所以问题是 - 如何以更具可读性和正确的方式做到这一点?

FWIW,“真实”案例场景是我通过创建像这样的无用脚本来玩 ES6:

https://jsfiddle.net/kpion/mqyrewnx/9/

我的疑虑是关于第 78 行//这是我的问题 - 似乎我需要在 YaLog 类之外进行。

编辑:顺便说一句 - 如果您带着类似的问题来到这里 - 以下所有答案都以某种方式回答了这个问题,而且都值得一读。感谢大家! :)

最佳答案

这种类原型(prototype)修改永远不会在构造函数内部执行——主要是因为类构造函数负责管理当前类实例,而不是所有类实例。构造函数应该在 this 类实例上声明新方法('log'、'info' 等),这比在类 prototype 上声明方法效率低,并且可能是否适合进一步的类继承。

这就是装饰器的用途。它们为扩展或修改类构造函数和原型(prototype)提供了方便的语法。

装饰器可以修改现有类原型(prototype):

function withLogger(Class) {
  ['log','info','error','warn','group','groupEnd'].forEach(func => {
    Class.prototype[func] = function() {
      return this.callConsoleMethod(func, ...arguments);
    };
  });

  return Class;
}

或者返回一个以非破坏性方式扩展现有类的新类,这允许在包装类中隐藏它们时使用 super 引用原始成员。

装饰器在 ECMAScript Next/TypeScript 中具有简洁的语法:

@withLogger
class YaLog {
  ...
}

由于装饰器基本上是一个辅助函数,它可以直接在 ES6 中以一种不太表达的方式应用:

const YaLog = withLogger(class YaLog {
  ...
});

关于javascript - 如何在运行时在此类中更改类的原型(prototype)(使用 ES6 类),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50161668/

相关文章:

javascript - Google 从本地主机登录中的 idpiframe_initialization_failed

javascript - 在没有 openFile 对话框的情况下将文件从客户端上传到服务器

javascript - 访问和更改 javascript 类中的数组值

javascript - 无法在控制台上使用扩展运算符参数记录字符串

javascript - 如何通过一个按钮添加一个或多个表单并通过javascript通过另一个按钮将其删除

javascript - 如何在存储到数组中的 forEach 中返回响应/ promise ?

javascript - 更改全日历的 View 不保留事件

javascript - 使用 Set 从数组中删除重复项,保留最高的 id

javascript - 如何避免在javascript中等待 hell

javascript - 如何使用 forEach 制作部分和的列表