如何验证JavaScript对象中的方法是否遵循特定接口?

时间:2018-04-19 07:41:37

标签: javascript node.js

我是JS的新手,我遇到过这种情况,我需要确定JS对象中定义的方法是否遵循特定的接口。

让我在一个例子的帮助下解释:

let logger1 = {
    log: function(message, meta){
        //logging functionality
    }
};

let logger2 = {
    log: function(level, message, meta){
        //logging functionality
    }
}

有2个记录器对象(logger1或logger2),它们有自己的记录功能。它们可以从客户端传递到客户端消耗的库。
库期望log方法属于特定的接口,这在库文档中已经提到过。在库内部,我们如何验证传入的记录器对象是否具有与接口匹配的“log”方法,库是否期望?

let Library = function(logger){
    //Here I can verify if the 'log' function is defined. But how do i make sure the log 
    //function matches the interface that the library is expecting ?     
    //Let's say the interface that the library is expecting is function(level,message,meta),
    //which is satisfied only by logger2.
    if(logger && typeof(logger.log) === 'function'){
        this.logger = logger;
    }
    else{
        this.logger = console;
    }
}

let lib1 = new Library(logger1);
let lib2 = new Library(logger2);

3 个答案:

答案 0 :(得分:3)

你不能真的。 Javascript函数可以省略它不使用的参数,因此该函数可能具有更少的参数并且仍然兼容。该函数可以定义 more 参数,如果没有传递将成为undefined,因此仍然是兼容的。它可能在内部使用arguments,因此没有定义任何参数,仍然兼容。它可以以任何方式命名它的任何参数,并且仍然兼容,因此即使检查参数名称也无济于事。

你唯一可以做的就是使用Typescript之类的东西并添加编译时检查。

答案 1 :(得分:1)

嗯,狡猾的。 我们先确定接口然后再实现。在这种情况下,我们会将logger1编码为签名:( message, meta )和logger2 ( message, meta, level )

这样我们就可以调用任何一个函数。 ( 'test', 'extra', 1 )和logger1将忽略level参数。

如果你使用的系统必须兼顾很多不同的论证版本,那么每次只使用一个对象作为唯一的参数可能会更好:function( config )并且只需在需要时添加额外的属性。 这样你也可以强制界面保持不变,同时也可以某种方式扩展。

答案 2 :(得分:0)

函数有一个属性长度属性,它给出了它拥有的参数数量

示例:

let logger1 = {
    log: function(message, meta){
        //logging functionality
    }
};
console.log(logger1.log.length); // 2

let logger2 = {
    log: function(level, message, meta){
        //logging functionality
    }
}
console.log(logger2.log.length); // 3