JavaScript是否具有接口types(如Java的“接口”)?

我正在学习如何使用JavaScript进行OOP 。 它有界面的概念(如Java的interface )吗?

所以我可以创build一个侦听器…

没有“这个类必须具备这些function”的概念(也就是说,本身没有接口),因为:

  1. JavaScriptinheritance基于对象,而不是类。 在你意识到之前,这不是一件大事。
  2. JavaScript是一种非常dynamic的types化语言,你可以用合适的方法创build一个对象,这样就可以使其符合接口, 然后取消定义所有符合要求的东西 。 破坏这个系统很容易 – 即使是偶然的! – 首先尝试build立一个types系统是不值得的。

相反,JavaScript使用所谓的鸭子打字 。 (如果它像鸭子一样走路,就像鸭子一样,就像JS一样,它就像一只鸭子。)如果你的对象有嘎嘎(),步行()和飞()方法,代码可以在任何需要的地方使用一个可以行走,嘎嘎和飞行的物体,而不需要实现一些“Duckable”界面。 这个接口就是代码使用的函数集合(以及这些函数的返回值),用鸭子打字,你可以免费获得这些。

现在,如果您尝试调用some_dog.quack() ,那么并不是说您的代码不会中途失败。 你会得到一个TypeError。 坦率地说,如果你告诉狗嘎嘎,你的问题会稍微大一些。 当你把所有的鸭子放在一排,可以说鸭子打字效果最好,不要让狗和鸭子混在一起,除非你把它们当作普通的动物来对待。 换句话说,即使界面是stream动的,它仍然在那里; 通过狗代码,往往是一个错误,它希望它嘎嘎和飞首先。

但是如果你确定自己做的是正确的事情,那么可以在尝试使用它之前通过testing特定方法的存在来解决qu狗问题。 就像是

 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对象根本没有.defineProperty ,而在IE8中,据称只能在主机对象(即DOM元素等)上工作。 如果兼容性问题,您不能使用.defineProperty 。 (我甚至不会提到IE6,因为它在中国以外已经不再那么重要了。)

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

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

拿起Dustin Diaz的“ JavaScriptdevise模式 ”的副本。 有几章专门通过鸭子键入来实现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 } 

JavaScript(ECMAScript版本3)有一个implements保留字,以备将来使用 。 我认为这只是为了这个目的,但是,急于将规范推出门外,他们没有时间来定义如何处理它,所以目前浏览器除了做什么之外什么也做不了让它坐在那里,偶尔抱怨,如果你尝试使用它的东西。

用一个逻辑来创build你自己的Object.implement(Interface)方法是可能的,也确实很简单,只要一个特定的属性/函数没有在给定的对象中实现,就会阻塞它。

我写了一篇关于面向对象的文章,使用我自己的符号如下

 // Create a 'Dog' class that inherits from 'Animal' // and implements the 'Mammal' interface var Dog = Object.extend(Animal, { constructor: function(name) { Dog.superClass.call(this, name); }, bark: function() { alert('woof'); } }).implement(Mammal); 

有很多方法来剥皮这个特定的猫,但这是我用于我自己的接口实现的逻辑。 我发现我更喜欢这种方法,并且很容易阅读和使用(如上所见)。 它的确意味着给Function.prototype增加一个'实现'的方法,有些人可能会遇到问题,但是我发现它运行的很好。

 Function.prototype.implement = function() { // Loop through each interface passed in and then check // that its members are implemented in the context object (this). for(var i = 0; i < arguments.length; i++) { // .. Check member's logic .. } // Remember to return the class being tested return this; } 

JavaScript接口:

虽然JavaScript没有interfacetypes,但通常是需要的。 由于JavaScript的dynamic性质和使用Prototypical-Inheritance的原因,很难确保跨类的一致接口 – 但是,可以这样做; 并经常效仿。

在这一点上,有一些特殊的方法来模拟JavaScript中的接口; 方法上的差异通常满足一些需求,而另一些则没有得到解决。 通常情况下,最健壮的方法过于繁琐,阻碍了实现者(开发者)。

下面是一个接口/抽象类的方法,它不是非常麻烦,是明确的,将抽象内部的实现保持在最低限度,并为dynamic或定制方法留下足够的空间:

 function resolvePrecept(interfaceName) { var interfaceName = interfaceName; return function curry(value) { /* throw new Error(interfaceName + ' requires an implementation for ...'); */ console.warn('%s requires an implementation for ...', interfaceName); return value; }; } var iAbstractClass = function AbstractClass() { var defaultTo = resolvePrecept('iAbstractClass'); this.datum1 = this.datum1 || defaultTo(new Number()); this.datum2 = this.datum2 || defaultTo(new String()); this.method1 = this.method1 || defaultTo(new Function('return new Boolean();')); this.method2 = this.method2 || defaultTo(new Function('return new Object();')); }; var ConcreteImplementation = function ConcreteImplementation() { this.datum1 = 1; this.datum2 = 'str'; this.method1 = function method1() { return true; }; this.method2 = function method2() { return {}; }; //Applies Interface (Implement iAbstractClass Interface) iAbstractClass.apply(this); // .call / .apply after precept definitions }; 

参与者

戒律parsing器

resolvePrecept函数是一个在抽象类中使用的实用程序和辅助函数。 它的工作是允许自定义实现处理封装的戒律(数据和行为) 。 它可以抛出错误或警告 – 并且 – 为实现者类指定一个默认值。

iAbstractClass

iAbstractClass定义要使用的接口。 其方法需要与其实施者类别达成默契。 这个接口将每个戒律分配给相同的戒律命名空间 – 或者 – 戒律parsing器函数返回的任何内容。 然而,默契协议的解决是一个背景 – 一个执行者的规定。

实施者

实现者只需与接口(在这种情况下是iAbstractClass )“同意”,并通过使用Constructor-HijackingiAbstractClass.apply(this) 。 通过定义上面的数据和行为,然后劫持 Interface的构造函数(将Implementor的上下文传递给Interface构造函数),我们可以确保将会添加Implementor的覆盖,Interface将会解释警告和默认值。

这是一个非常繁琐的方法,为我的团队和我在时间和不同项目上的工作提供了很好的帮助。 但是,它有一些警告和缺点。

缺点

虽然这有助于在很大程度上实现整个软件的一致性,但它并没有实现真正的接口 ,而是模拟它们。 虽然定义,默认值,警告或错误都被解释了,但开发人员强制使用和声明使用(与JavaScript开发的大部分内容一样)。

这似乎是“JavaScript中的接口”的最佳方法,但是,我希望看到以下解决scheme:

  • 断言返回types
  • 签名的断言
  • 冻结delete操作中的对象
  • 在JavaScript社区的特殊性中,任何其他stream行或需要的断言

也就是说,我希望这可以帮助你和我的团队和我一样

bob.js支持某种接口。

1.检查一个对象是否实现了一个接口:

 var iFace = { say: function () { }, write: function () { } }; var obj1 = { say: function() { }, write: function () { }, read: function () { } }; var obj2 = { say: function () { }, read: function () { } }; console.log('1: ' + bob.obj.canExtractInterface(obj1, iFace)); console.log('2: ' + bob.obj.canExtractInterface(obj2, iFace)); // Output: // 1: true // 2: false 

2.从一个对象中提取接口:

 var obj = { msgCount: 0, say: function (msg) { console.log(++this.msgCount + ': ' + msg); }, sum: function (a, b) { console.log(a + b); } }; var iFace = { say: function () { } }; obj = bob.obj.extractInterface(obj, iFace); obj.say('Hello!'); obj.say('How is your day?'); obj.say('Good bye!'); // Output: // 1: Hello! // 2: How is your day? // 3: Good bye! 

你需要Java中的接口,因为它是静态types的,在编译期间应该知道类之间的契约。 在JavaScript中是不同的。 JavaScript是dynamicinput的; 这意味着当你得到对象时,你可以检查它是否有一个特定的方法,并调用它。

我知道这是一个旧的,但我最近发现自己需要越来越多,有一个方便的API检查对象的接口。 所以我写了这个: https : //github.com/tomhicks/methodical

它也可以通过NPM: npm install methodical

它基本上做了上面提到的所有事情,有一些更严格的选项,而且不需要加载if (typeof x.method === 'function')样板。

希望有人认为它有用。

Javascript没有接口。 但是它可以是duck-typed,可以在这里find一个例子:

http://reinsbrain.blogspot.com/2008/10/interface-in-javascript.html

希望任何仍在寻找答案的人都能find帮助。

您可以尝试使用代理服务器(从ECMAScript 2015开始就是标准的): https : //developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy

 latLngLiteral = new Proxy({},{ set: function(obj, prop, val) { //only these two properties can be set if(['lng','lat'].indexOf(prop) == -1) { throw new ReferenceError('Key must be "lat" or "lng"!'); } //the dec format only accepts numbers if(typeof val !== 'number') { throw new TypeError('Value must be numeric'); } //latitude is in range between 0 and 90 if(prop == 'lat' && !(0 < val && val < 90)) { throw new RangeError('Position is out of range!'); } //longitude is in range between 0 and 180 else if(prop == 'lng' && !(0 < val && val < 180)) { throw new RangeError('Position is out of range!'); } obj[prop] = val; return true; } }); 

那么你可以很容易地说:

 myMap = {} myMap.position = latLngLiteral; 

还有jQuery.isFunction(方法),如果你愿意,而不是choao的代码。