JavaScript是否有接口类型(例如Java的“接口”)?

2022-08-29 23:25:47

我正在学习如何用JavaScript制作OOP。它有接口概念(如Java的)吗?interface

所以我将能够创建一个听众...


答案 1

没有“这个类必须具有这些函数”的概念(即,本身没有接口),因为:

  1. JavaScript继承基于对象,而不是类。在你意识到之前,这没什么大不了的:
  2. JavaScript是一种非常动态类型的语言 - 你可以用适当的方法创建一个对象,这将使它符合接口,然后取消定义所有使它符合的东西。颠覆类型系统是很容易的 - 即使是偶然的!- 首先尝试制作一个类型系统是不值得的。

相反,JavaScript使用所谓的鸭子类型。(如果它像鸭子一样走路,像鸭子一样嘎嘎叫,就JS所关心的,它就是一只鸭子。如果你的对象有 quack()、walk() 和 fly() 方法,代码可以在任何需要可以走路、嘎嘎和飞翔的对象的地方使用它,而不需要实现一些“Duckable”接口。该接口正是代码使用的函数集(以及这些函数的返回值),通过 duck 键入,您可以免费获得该函数。

现在,这并不是说你的代码不会在中途失败,如果你尝试调用;你会得到一个TypeError。坦率地说,如果你告诉狗嘎嘎叫,你有更大的问题;鸭子打字最好当你把所有的鸭子都排成一排,可以这么说,除非你把它们当作普通动物,否则不要让狗和鸭子混在一起。换句话说,即使界面是流动的,它仍然在那里;将狗传递给期望它首先嘎嘎作响并飞行的代码通常是一个错误。some_dog.quack()

但是,如果你确定你正在做正确的事情,你可以通过在尝试使用特定方法之前测试它的存在来解决庸医问题。类似的东西

if (typeof(someObject.quack) == "function")
{
    // This thing can quack
}

因此,您可以在使用它们之前检查可以使用的所有方法。不过,语法有点丑陋。有一种稍微漂亮的方法:

Object.prototype.can = function(methodName)
{
     return ((typeof this[methodName]) == "function");
};

if (someObject.can("quack"))
{
    someObject.quack();
}

这是标准的JavaScript,所以它应该在任何值得使用的JS解释器中工作。它具有像英语一样阅读的额外好处。

对于现代浏览器(即,除了IE 6-8之外,几乎任何浏览器),甚至有一种方法可以防止属性显示在:for...in

Object.defineProperty(Object.prototype, 'can', {
    enumerable: false,
    value: function(method) {
        return (typeof this[method] === 'function');
    }
}

问题在于IE7对象根本没有,在IE8中,它据称仅适用于主机对象(即DOM元素等)。如果兼容性是一个问题,则不能使用 .(我甚至不会提到IE6,因为它在中国以外的地方已经无关紧要了。.defineProperty.defineProperty

另一个问题是,一些编码风格喜欢假设每个人都写了糟糕的代码,并禁止修改以防有人想盲目使用。如果您关心这一点,或者正在使用(IMO损坏的)代码,请尝试稍微不同的版本:Object.prototypefor...in

function can(obj, methodName)
{
     return ((typeof obj[methodName]) == "function");
}

if (can(someObject, "quack"))
{
    someObject.quack();
}

答案 2

拿起一份Dustin Diaz的“JavaScript设计模式”。有几章专门介绍如何通过 Duck Typing 实现 JavaScript 接口。这也是一本不错的读物。但是不,没有语言原生实现的接口,你必须鸭子类型

// example duck typing method
var hasMethods = function(obj /*, method list as strings */){
    var i = 1, methodName;
    while((methodName = arguments[i++])){
        if(typeof obj[methodName] != 'function') {
            return false;
        }
    }
    return true;
}

// in your code
if(hasMethods(obj, 'quak', 'flapWings','waggle')) {
    //  IT'S A DUCK, do your duck thang
}