通过原型链在 JavaScript 中定义接口
Defining an interface in JavaScript via prototype chain
我知道在 C++ 等多种语言中,您可以创建具有多重继承的 classes(或者至少使用 Java 中的接口来模拟它)。在Java脚本中,是否可以定义一个可以在class上实现的接口?如果是这样,最好的方法是什么,最好以某种方式合并原型链。下面行不行,还是有更好的办法?
function Gizmo() {
console.log('Gizmo constructed');
}
Gizmo.prototype.wamboozle = function () {
console.log('wamboozle');
};
function EventEmitter() {
console.log('EventEmitter constructed');
this.events = {};
}
EventEmitter.prototype.on = function (name, callback) {
this.events[name] ? this.events[name].push(callback) : (this.events[name] = [callback]);
};
EventEmitter.prototype.emit = function (name, event) {
if (this.events[name]) {
this.events[name].forEach(function (callback) {
callback(event);
});
}
};
// set up inheritance and implementation
// maybe this could be a possibility?
Doohickey.prototype = Object.create(Gizmo.prototype);
Object.getOwnPropertyNames(EventEmitter.prototype).forEach(function (member) {
Doohickey.prototype[member] = EventEmitter.prototype[member];
});
function Doohickey() {
console.log('Doohickey constructed');
Gizmo.call(this); // initialize base class
EventEmitter.call(this); // initialize interface
}
Doohickey.prototype.turlywoops = function () {
console.log('turlywoops');
};
var myOwnDoohickey = new Doohickey();
// member function works
myOwnDoohickey.turlywoops();
// inherited member function works
myOwnDoohickey.wamboozle();
// interface member functions work
myOwnDoohickey.on('finagle', function (trick) {
console.log(trick);
});
myOwnDoohickey.emit('finagle', {
hello: 'world!'
});
// both true
console.log(myOwnDoohickey instanceof Doohickey);
console.log(myOwnDoohickey instanceof Gizmo);
// don't mind if this isn't necessarily true, though it would be nice
console.log(myOwnDoohickey instanceof EventEmitter);
你不能在任何级别继承超过 1 个原型(尽管你可以有一个继承堆栈),并且接口没有意义,因为 javascript 是一种动态语言并且搜索整个原型链用于匹配名称。没有通过接口访问对象的概念。
在JavaScript中你最多可以定义一个Object,它会被你的Object继承。 对象的继承也被你的对象继承,等等,长链。
function Foo() {
this.fooThisProp = 'tfoo';
}
Foo.prototype = Object.create(null);
Foo.prototype.fooProtoProp = 'pfoo';
function Bar() {
Foo.call(this);
this.barThisProp = 'tbar';
}
Bar.prototype = Object.create(Foo.prototype);
Bar.prototype.barProtoProp = 'pbar';
function Baz() {
Bar.call(this);
this.bazThisProp = 'tbaz';
}
Baz.prototype = Object.create(Bar.prototype);
Baz.prototype.bazProtoProp = 'pbaz';
var obj = new Baz();
obj; // {barThisProp: "tbar", bazThisProp: "tbaz", fooThisProp: "tfoo"}
obj.bazProtoProp; // "pbaz"
obj.barProtoProp; // "pbar"
obj.fooProtoProp; // "pfoo"
obj instanceof Baz; // true
obj instanceof Bar; // true
obj instanceof Foo; // true
您始终可以将构造函数应用于 Object,它不是实例,因此不会从该构造函数继承。请注意构造函数不会假定继承方法等的存在,
var fizz = {};
Bar.call(fizz);
fizz; // {barThisProp: "tbar", fooThisProp: "tfoo"}
fizz.barProtoProp; // undefined
fizz.fooProtoProp; // undefined
fizz instanceof Bar; // false
fizz instanceof Foo; // false
如果你想编写一个方法包装器来做事情,那么你可以在任何 context[=13 中使用几乎任何 Object =]
function Buzz() {}
Buzz.prototype = Object.create(null); // Buzz separate from Foo, Bar, Baz
Buzz.prototype.bazLook = function (key) {
return Baz.prototype[key]; // or do something else with the value
}
var buzz = new Buzz();
buzz.bazLook('fooProtoProp'); // "pfoo"
使用类似 underscore.js 的方法,您可以基于两个不相关的原型创建一个新对象并将其用作原型。在此示例中,obj2 中定义的 properties/methods 将覆盖结果对象中 obj1 中的任何内容。
function IAmMulti(){
}
IAmMulti.prototype=_.extend(_.clone(Obj1.prototype),_.clone(Obj2.prototype));
这是一个例子:JavaScript inheritance with _.extend()
我知道在 C++ 等多种语言中,您可以创建具有多重继承的 classes(或者至少使用 Java 中的接口来模拟它)。在Java脚本中,是否可以定义一个可以在class上实现的接口?如果是这样,最好的方法是什么,最好以某种方式合并原型链。下面行不行,还是有更好的办法?
function Gizmo() {
console.log('Gizmo constructed');
}
Gizmo.prototype.wamboozle = function () {
console.log('wamboozle');
};
function EventEmitter() {
console.log('EventEmitter constructed');
this.events = {};
}
EventEmitter.prototype.on = function (name, callback) {
this.events[name] ? this.events[name].push(callback) : (this.events[name] = [callback]);
};
EventEmitter.prototype.emit = function (name, event) {
if (this.events[name]) {
this.events[name].forEach(function (callback) {
callback(event);
});
}
};
// set up inheritance and implementation
// maybe this could be a possibility?
Doohickey.prototype = Object.create(Gizmo.prototype);
Object.getOwnPropertyNames(EventEmitter.prototype).forEach(function (member) {
Doohickey.prototype[member] = EventEmitter.prototype[member];
});
function Doohickey() {
console.log('Doohickey constructed');
Gizmo.call(this); // initialize base class
EventEmitter.call(this); // initialize interface
}
Doohickey.prototype.turlywoops = function () {
console.log('turlywoops');
};
var myOwnDoohickey = new Doohickey();
// member function works
myOwnDoohickey.turlywoops();
// inherited member function works
myOwnDoohickey.wamboozle();
// interface member functions work
myOwnDoohickey.on('finagle', function (trick) {
console.log(trick);
});
myOwnDoohickey.emit('finagle', {
hello: 'world!'
});
// both true
console.log(myOwnDoohickey instanceof Doohickey);
console.log(myOwnDoohickey instanceof Gizmo);
// don't mind if this isn't necessarily true, though it would be nice
console.log(myOwnDoohickey instanceof EventEmitter);
你不能在任何级别继承超过 1 个原型(尽管你可以有一个继承堆栈),并且接口没有意义,因为 javascript 是一种动态语言并且搜索整个原型链用于匹配名称。没有通过接口访问对象的概念。
在JavaScript中你最多可以定义一个Object,它会被你的Object继承。 对象的继承也被你的对象继承,等等,长链。
function Foo() {
this.fooThisProp = 'tfoo';
}
Foo.prototype = Object.create(null);
Foo.prototype.fooProtoProp = 'pfoo';
function Bar() {
Foo.call(this);
this.barThisProp = 'tbar';
}
Bar.prototype = Object.create(Foo.prototype);
Bar.prototype.barProtoProp = 'pbar';
function Baz() {
Bar.call(this);
this.bazThisProp = 'tbaz';
}
Baz.prototype = Object.create(Bar.prototype);
Baz.prototype.bazProtoProp = 'pbaz';
var obj = new Baz();
obj; // {barThisProp: "tbar", bazThisProp: "tbaz", fooThisProp: "tfoo"}
obj.bazProtoProp; // "pbaz"
obj.barProtoProp; // "pbar"
obj.fooProtoProp; // "pfoo"
obj instanceof Baz; // true
obj instanceof Bar; // true
obj instanceof Foo; // true
您始终可以将构造函数应用于 Object,它不是实例,因此不会从该构造函数继承。请注意构造函数不会假定继承方法等的存在,
var fizz = {};
Bar.call(fizz);
fizz; // {barThisProp: "tbar", fooThisProp: "tfoo"}
fizz.barProtoProp; // undefined
fizz.fooProtoProp; // undefined
fizz instanceof Bar; // false
fizz instanceof Foo; // false
如果你想编写一个方法包装器来做事情,那么你可以在任何 context[=13 中使用几乎任何 Object =]
function Buzz() {}
Buzz.prototype = Object.create(null); // Buzz separate from Foo, Bar, Baz
Buzz.prototype.bazLook = function (key) {
return Baz.prototype[key]; // or do something else with the value
}
var buzz = new Buzz();
buzz.bazLook('fooProtoProp'); // "pfoo"
使用类似 underscore.js 的方法,您可以基于两个不相关的原型创建一个新对象并将其用作原型。在此示例中,obj2 中定义的 properties/methods 将覆盖结果对象中 obj1 中的任何内容。
function IAmMulti(){
}
IAmMulti.prototype=_.extend(_.clone(Obj1.prototype),_.clone(Obj2.prototype));
这是一个例子:JavaScript inheritance with _.extend()