There's no notion of "this class must have these functions" (that is, no interfaces per se), because:(没有“这个类必须具有这些功能”的概念(即,本身没有接口),因为:)
JavaScript inheritance is based on objects, not classes.(JavaScript继承基于对象,而不是类。) That's not a big deal until you realize:(直到你意识到这一点并不重要:)
JavaScript is an extremely dynamically typed language -- you can create an object with the proper methods, which would make it conform to the interface, and then undefine all the stuff that made it conform .(JavaScript是一种极其动态类型的语言 - 您可以使用适当的方法创建一个对象,这将使其符合接口, 然后取消定义使其符合的所有内容 。) It'd be so easy to subvert the type system -- even accidentally!(破坏类型系统很容易 - 甚至意外!) -- that it wouldn't be worth it to try and make a type system in the first place.( - 首先尝试制作类型系统是不值得的。)
Instead, JavaScript uses what's called duck typing .(相反,JavaScript使用所谓的duck typing 。) (If it walks like a duck, and quacks like a duck, as far as JS cares, it's a duck.) If your object has quack(), walk(), and fly() methods, code can use it wherever it expects an object that can walk, quack, and fly, without requiring the implementation of some "Duckable" interface.((如果它像鸭子一样走路,像鸭子那样呱呱叫,就JS而言,它就是鸭子。)如果你的对象有quack(),walk()和fly()方法,代码可以在任何预期的地方使用它一个可以行走,嘎嘎叫和飞行的物体,而不需要实现一些“Duckable”接口。) The interface is exactly the set of functions that the code uses (and the return values from those functions), and with duck typing, you get that for free.(接口正是代码使用的函数集(以及这些函数的返回值),并且使用duck typing,您可以免费获得。)
Now, that's not to say your code won't fail halfway through, if you try to call some_dog.quack()
;(现在,如果你试图调用some_dog.quack()
,那并不是说你的代码不会中途失败。) you'll get a TypeError.(你会得到一个TypeError。) Frankly, if you're telling dogs to quack, you have slightly bigger problems;(坦率地说,如果你告诉狗嘎嘎叫,你会遇到更大的问题;) duck typing works best when you keep all your ducks in a row, so to speak, and aren't letting dogs and ducks mingle together unless you're treating them as generic animals.(当你把所有的鸭子连成一排时,鸭子的打字效果最好,可以这么说,除非你把它们视为一般动物,否则它们不会让狗和鸭子混在一起。) In other words, even though the interface is fluid, it's still there;(换句话说,即使界面是流动的,它仍然存在;) it's often an error to pass a dog to code that expects it to quack and fly in the first place.(将狗传递给期望它首先嘎嘎叫并飞行的代码通常是错误的。)
But if you're sure you're doing the right thing, you can work around the quacking-dog problem by testing for the existence of a particular method before trying to use it.(但是如果你确定你做的是正确的事情,你可以通过在尝试使用之前测试特定方法的存在来解决这个问题。) Something like(就像是)
if (typeof(someObject.quack) == "function")
{
// This thing can quack
}
So you can check for all the methods you can use before you use them.(因此,您可以在使用之前检查可以使用的所有方法。) The syntax is kind of ugly, though.(不过,语法有点难看。) There's a slightly prettier way:(有一个更漂亮的方式:)
Object.prototype.can = function(methodName)
{
return ((typeof this[methodName]) == "function");
};
if (someObject.can("quack"))
{
someObject.quack();
}
This is standard JavaScript, so it should work in any JS interpreter worth using.(这是标准的JavaScript,所以它应该适用于任何值得使用的JS解释器。) It has the added benefit of reading like English.(它具有英语阅读的额外好处。)
For modern browsers (that is, pretty much any browser other than IE 6-8), there's even a way to keep the property from showing up in for...in
:(对于现代浏览器(即几乎任何除IE 6-8之外的浏览器),甚至还有一种方法可以防止该属性出现在for...in
:)
Object.defineProperty(Object.prototype, 'can', {
enumerable: false,
value: function(method) {
return (typeof this[method] === 'function');
}
}
The problem is that IE7 objects don't have .defineProperty
at all, and in IE8, it allegedly only works on host objects (that is, DOM elements and such).(问题是IE7对象根本没有.defineProperty
,而在IE8中,它据称只适用于主机对象(即DOM元素等)。) If compatibility is an issue, you can't use .defineProperty
.(如果兼容性是个问题,则不能使用.defineProperty
。) (I won't even mention IE6, because it's rather irrelevant anymore outside of China.)((我甚至不会提到IE6,因为它在中国之外已经相当无关紧要了。))
Another issue is that some coding styles like to assume that everyone writes bad code, and prohibit modifying Object.prototype
in case someone wants to blindly use for...in
.(另一个问题是,某些编码样式会假设每个人都编写错误的代码,并禁止修改Object.prototype
,以防有人想盲目地使用for...in
。) If you care about that, or are using (IMO broken ) code that does, try a slightly different version:(如果您关心它,或者正在使用(IMO 损坏的 )代码,请尝试稍微不同的版本:)
function can(obj, methodName)
{
return ((typeof obj[methodName]) == "function");
}
if (can(someObject, "quack"))
{
someObject.quack();
}
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…