Javascript 是否可以在实例化时检测所有给定类型';s可调用的方法,然后为每个方法动态创建一个转发进程

Javascript 是否可以在实例化时检测所有给定类型';s可调用的方法,然后为每个方法动态创建一个转发进程,javascript,class,methods,dynamic,Javascript,Class,Methods,Dynamic,我需要一种聚合类,将它的方法调用转发给它的所有组成部分。这是我写的: 类复合脚本{ 精灵=[];//收集精灵表对象 画(){ this.sprites.forEach(s=>(s.draw.apply(s,参数))) } init(){ this.sprites.forEach(s=>(s.init.apply(s,参数))) } 下一步(){ this.sprites.forEach(s=>(s.nextStep.apply(s,参数))) } //…用于所有可能的功能 } let board

我需要一种聚合类,将它的方法调用转发给它的所有组成部分。这是我写的:

类复合脚本{
精灵=[];//收集精灵表对象
画(){
this.sprites.forEach(s=>(s.draw.apply(s,参数)))
}
init(){
this.sprites.forEach(s=>(s.init.apply(s,参数)))
}
下一步(){
this.sprites.forEach(s=>(s.nextStep.apply(s,参数)))
}
//…用于所有可能的功能
}
let board=新的Spritesheet(“a”);
让文本=新的子画面(“b”);
让composite=newcompositespritesheet();
合成。精灵。推(木头,文字);
复合拉伸(20,30);
这段代码实际上是重复的,不是穷尽的,可能会因意外的函数调用而失败,最重要的是,它非常讨厌。有没有一种方法可以将其推广,或许可以编写一个更高阶的类,在突发奇想的情况下生成这样的合成

换句话说,JavaScript中是否有一种机制可以让我复制以下伪代码的行为

class CompositeSpritesheet{
    sprites = [];
    *("fn", args){
        this.sprites.forEach(s => (s[fn]?.apply(s, arguments)))
    }
}
这可能是一个愚蠢的问题,但我发现JavaScript在许多意想不到的方面都很灵活,我还没有完全理解。我觉得它可能以某种形式出现

如果您的想法不能完全回答问题,但仍然与解决方案相关,请随时将其作为评论发布。

编辑:

根据另一个答案中的注释,您可以创建类,然后将函数添加到原型中:

class CompositeSpritesheet {
    sprites = [];
};

var functionsToCreate = ["draw", "init", "nextStep"];

for (let f of functionsToCreate) {
    CompositeSpritesheet.prototype[f] = function() {
        this.sprites.forEach(s => (s[f].apply(s, arguments)));
    }
}
因此CompositeSpritesheet将在其原型中具有您想要的所有功能,因此您将能够调用
composite.draw(20,30)

您只需填写
函数来创建
数组

=====================

我看到的一个解决方案可能是只调用一个具有不同参数的方法:

class CompositeSpritesheet {
    function doSomething(action, args) {
        this.sprites.forEach(s => (s[action].apply(s, args)));
}

因此您可以调用
composite.doSomething(“draw”,[20,30])

。。。像这样的东西

class CompositeSpritesheet {
  constructor(...sprites) {
    let spriteList = [].concat(...sprites);

    this.addSprites = (...sprites) => {
      spriteList = spriteList.concat(...sprites);
    };
    this.execute = (actionName, ...args) => {
      spriteList.forEach(sprite => {

        const action = sprite[actionName];
        if (typeof action === 'function') {

          action.apply(sprite, args);
        }
      });
    };
  }
}

let board = new Spritesheet("a");
let text = new Spritesheet("b");

let composite = new CompositeSpritesheet();

composite.addSprites(board, text);
composite.execute('draw', 20, 30);
编辑/第二次迭代 接下来提供的方法是通用方法。知道在任何时候,每个内部列出的
Spritesheet
类型都具有相同的方法集,新引入的
CompositeSpritesheet
类型现在都会在构建时或一个(或多个)元素之后检测其第一个列出的
Spritesheet
元素的所有可访问键将连接到复合类型的内部管理的精灵表列表。然后,在迭代这个键列表时,为每个找到的spritesheet方法动态创建一个对应的转发器方法

。。。工作示例代码

函数为布尔值(类型){
返回值(typeof type==='boolean');
}
函数isNumberValue(类型){
返回(typeof type=='number');
}
函数isStringValue(类型){
return(typeof type==='string');
}
函数isSymbol(类型){
返回值(typeof type==='symbol');
}
函数isPrimitive(类型){
返回(
isBooleanValue(类型)
||isNumberValue(类型)
||isStringValue(类型)
||isSymbol(类型)
);
}
功能对象(类型){
返回(!!type&&(typeof type==='object');
}
函数isFunction(类型){
const functionType='function';
返回(
(类型的类型===函数类型)
&&(typeof type.call===functionType)
&&(typeof type.apply===函数类型)
);
}
/**
*-递归收集类型的可访问键列表
*这也可能是继承的,但它们都不是键
*不是'Object.prototype'的键,也不是'Function.prototype'的键。
*/
函数getAllAccessiblePropertyNames(类型,键列表){
//默认返回值。
keyList=(keyList | |[]);
//也接受基本数据类型。
if(isPrimitive(type)){
类型=对象(类型);
}
//未定义值和空值被保留。
if(等分对象(类型)){
keyList=keyList.concat(
对象。键(类型)
)康卡特先生(
Object.getOwnPropertyNames(类型)
);
constprototype=(isFunction(type.constructor)和&type.constructor.protoType);
if(protoType&(protoType!==Object.protoType)){
if(protoType==protoType.constructor.protoType){
keyList=keyList.concat(
Object.keys(原型)
)康卡特先生(
Object.getOwnPropertyNames(原型)
);
}否则{
keyList=getAllAccessiblePropertyNames(原型,keyList);
}
}
const proto=类型;
if((isObject(proto)| isFunction(proto))&&(proto!==Object.prototype)){
if(proto==proto.\uuuu proto\uuuuu){
keyList=keyList.concat(
Object.keys(proto)
)康卡特先生(
Object.getOwnPropertyNames(proto)
);
}否则{
keyList=getAllAccessiblePropertyNames(proto,keyList);
}
}
}
返回[…(新集合(键列表))].filter(键=>!(/^\d+$/).test(键));
}
函数isEmptyList(类型){
返回((类型=对象(类型))&&('length'在类型中)&&(Array.from(类型).length==0));
}
带有PriteSheetForwardMethods的函数(sharedState){
//守卫。
if(sharedState.hasForwarderMethods | | isEmptyList(sharedState.spritesheetList)){
//要么已经有了所有的方法,要么仍然没有可以使用的方法。
返回;
}
const compositeType=this;
常量spritesheetType=sharedState.spritesheetList[0];
getAllAccessiblePropertyNames(spritesheetType).forEach((键)=>{
if(isFunction(spritesheetType[key])){
//应用spritesheet转发器方法。
compositeType[key]=函数(…参数){
sharedState.spritesheetList.forEach(
(spritesheet)=>spritesheet[key]。应用(spritesheet,args)
);
}
}
});
sharedState.hasForwarderMethods=true;
}
具有PriteSheetListManagement(sharedState)的函数{
const compositeType=this;
复合类型。