我正在学习如何用JavaScript制作面向对象编程。是否有接口概念(如Java的接口)?
这样我就可以创建一个监听器。
我正在学习如何用JavaScript制作面向对象编程。是否有接口概念(如Java的接口)?
这样我就可以创建一个监听器。
当前回答
当你想使用转换器时,你可以尝试TypeScript。它支持ECMA草案特性(在提案中,接口被称为“协议”),类似于coffeescript或babel等语言。
在TypeScript中,你的界面看起来是这样的:
interface IMyInterface {
id: number; // TypeScript types are lowercase
name: string;
callback: (key: string; value: any; array: string[]) => void;
type: "test" | "notATest"; // so called "union type"
}
你不能做的:
为类型值定义RegExp模式 定义验证,比如字符串长度 数量范围 等。
其他回答
像这样的抽象接口
const MyInterface = {
serialize: () => {throw "must implement serialize for MyInterface types"},
print: () => console.log(this.serialize())
}
创建一个实例:
function MyType() {
this.serialize = () => "serialized "
}
MyType.prototype = MyInterface
并使用它
let x = new MyType()
x.print()
试试这个方法:将接口描述为一个类,并使用@implements JSDoc来显示给定的类实现了定义的接口。如果它没有实现某些属性,你会在类名上看到红色的弯曲线。我用VSCode进行了测试。
// @ts-check
// describe interface using a class
class PlainInterface {
size = 4;
describe() {}
show(){ }
}
/**
* @implements PlainInterface
*/
class ConcretePlain {
size = 4;
describe() {
console.log('I am described')
}
show(){
console.log('I am shown')
}
}
const conc = new ConcretePlain();
conc.describe();
JavaScript (ECMAScript edition 3)有一个保留字以备将来使用。我认为这正是为了这个目的而设计的,然而,在匆忙发布规范的过程中,他们没有时间定义如何使用它,所以,目前,浏览器除了让它呆在那里,偶尔会抱怨你试图用它来做什么之外,什么也不做。
创建自己的object. implementation (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中添加一个“实现”方法。原型,有些人可能有一个问题,但我发现它工作得很漂亮。
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;
}
Js没有接口,但typescript有!
找到一个尽可能低影响的模拟接口的解决方案也困扰着我。
一种解决方案是制作一个工具:
/**
@parameter {Array|object} required : method name list or members types by their name
@constructor
*/
let Interface=function(required){
this.obj=0;
if(required instanceof Array){
this.obj={};
required.forEach(r=>this.obj[r]='function');
}else if(typeof(required)==='object'){
this.obj=required;
}else {
throw('Interface invalid parameter required = '+required);
}
};
/** check constructor instance
@parameter {object} scope : instance to check.
@parameter {boolean} [strict] : if true -> throw an error if errors ar found.
@constructor
*/
Interface.prototype.check=function(scope,strict){
let err=[],type,res={};
for(let k in this.obj){
type=typeof(scope[k]);
if(type!==this.obj[k]){
err.push({
key:k,
type:this.obj[k],
inputType:type,
msg:type==='undefined'?'missing element':'bad element type "'+type+'"'
});
}
}
res.success=!err.length;
if(err.length){
res.msg='Class bad structure :';
res.errors=err;
if(strict){
let stk = new Error().stack.split('\n');
stk.shift();
throw(['',res.msg,
res.errors.map(e=>'- {'+e.type+'} '+e.key+' : '+e.msg).join('\n'),
'','at :\n\t'+stk.join('\n\t')
].join('\n'));
}
}
return res;
};
使用实例:
// create interface tool
let dataInterface=new Interface(['toData','fromData']);
// abstract constructor
let AbstractData=function(){
dataInterface.check(this,1);// check extended element
};
// extended constructor
let DataXY=function(){
AbstractData.apply(this,[]);
this.xy=[0,0];
};
DataXY.prototype.toData=function(){
return [this.xy[0],this.xy[1]];
};
// should throw an error because 'fromData' is missing
let dx=new DataXY();
与类
class AbstractData{
constructor(){
dataInterface.check(this,1);
}
}
class DataXY extends AbstractData{
constructor(){
super();
this.xy=[0,0];
}
toData(){
return [this.xy[0],this.xy[1]];
}
}
它仍然有一点性能的提高,并且需要依赖于Interface类,但是可以用于调试或开放api。