没有“这个类必须有这些函数”的概念(即没有接口本身),因为:
> JavaScript继承是基于对象,而不是类。这不是一个大问题,直到你意识到:
> JavaScript是一种极其动态类型的语言 – 您可以使用适当的方法创建一个对象,这将使它符合接口,然后取消定义所有符合的东西。这将是那么容易颠覆类型系统 – 即使意外! – 它不值得尝试,并建立一个类型系统在第一位。
相反,JavaScript使用所谓的duck typing.(如果它像鸭子一样行走,像鸭子一样,就像JS一样,它是一个鸭子。)如果你的对象有quack(),walk()和fly ,代码可以使用它,无论它期望一个对象可以走,嘎嘎和飞,而不需要实现一些“Duckable”接口。接口正是代码使用的函数集(以及这些函数的返回值),并且通过鸭式输入,您可以免费获得。
现在,这不是说你的代码不会失败中途,如果你尝试调用some_dog.quack();你会得到一个TypeError。坦率地说,如果你告诉狗嘎嘎叫,你有更大的问题;鸭子打字的效果最好,当你把所有的鸭子在一排,可以说,不是让狗和鸭子在一起,除非你把它们当作通用动物。换句话说,即使界面是流体,它仍然存在;它通常是一个错误,传递一个狗到代码,希望它嘎嘎和飞在第一位。
但是如果你确信你做的正确的事情,你可以通过测试一个特定的方法的存在来尝试使用它之前解决狗狗问题。就像是
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),甚至有一种方法来阻止属性显示在…中:
Object.defineProperty(Object.prototype, 'can', {
enumerable: false,
value: function(method) {
return (typeof this[method] === 'function');
}
}
问题是IE7对象根本没有.defineProperty,在IE8中,据称它只对主机对象(即DOM元素等)起作用。如果兼容性是一个问题,您不能使用.defineProperty。 (我甚至不会提及IE6,因为它在中国以外是相当不相关的。)
另一个问题是,一些编码风格喜欢假设每个人都写错误的代码,并禁止修改Object.prototype以防有人想盲目使用…。如果你关心,或正在使用(IMO破碎)代码,尝试略有不同的版本:
function can(obj, methodName)
{
return ((typeof obj[methodName]) == "function");
}
if (can(someObject, "quack"))
{
someObject.quack();
}