假设您有以下代码:
function A() {
function modify(){
x = 300;
y = 400;
}
var c = new C();
}
function B() {
function modify(){
x = 3000;
y = 4000;
}
var c = new C();
}
C = function () {
var x = 10;
var y = 20;
function modify() {
x = 30;
y = 40;
};
modify();
alert("The sum is: " + (x+y));
}
现在问题是,如果有任何方法,我可以使用A和B中的方法覆盖C中的方法modify
。在Java中你会使用super关键字,但你怎么能在JavaScript中实现这样的东西?
答案 0 :(得分:122)
编辑:现在已经有六年了,原来的答案已经写好了,而且已经发生了很多变化!
JavaScript继承看起来与Java略有不同。以下是本机JavaScript对象系统的外观:
// Create a class
function Vehicle(color){
this.color = color;
}
// Add an instance method
Vehicle.prototype.go = function(){
return "Underway in " + this.color;
}
// Add a second class
function Car(color){
this.color = color;
}
// And declare it is a subclass of the first
Car.prototype = new Vehicle();
// Override the instance method
Car.prototype.go = function(){
return Vehicle.prototype.go.call(this) + " car"
}
// Create some instances and see the overridden behavior.
var v = new Vehicle("blue");
v.go() // "Underway in blue"
var c = new Car("red");
c.go() // "Underway in red car"
不幸的是,这有点难看,它不包含一个非常好的“超级”方式:你必须手动指定要调用哪个父类的方法。因此,有许多工具可以使创建类更好。尝试查看Prototype.js,Backbone.js或类似的库,其中包含在js中执行OOP的更好的语法。
答案 1 :(得分:32)
由于这是Google的热门话题,我想提供更新的答案。
使用ES6 classes使继承和方法覆盖变得更加容易:
'use strict';
class A {
speak() {
console.log("I'm A");
}
}
class B extends A {
speak() {
super.speak();
console.log("I'm B");
}
}
var a = new A();
a.speak();
// Output:
// I'm A
var b = new B();
b.speak();
// Output:
// I'm A
// I'm B
super
keyword在继承类中使用时引用父类。此外,父类的所有方法都绑定到子实例,因此您不必编写super.method.apply(this);
。
至于兼容性:the ES6 compatibility table仅显示主要播放器支持类的最新版本(主要是)。 V8浏览器从今年1月开始就已经有了它们(Chrome和Opera),使用SpiderMonkey JS引擎的Firefox将在下个月推出官方Firefox 45版本。在移动端,Android仍然不支持此功能,而五个月前发布的iOS 9部分支持。
幸运的是,有Babel,一个JS库,用于将Harmony代码重新编译为ES5代码。 ES6中的类和许多其他很酷的功能可以使您的Javascript代码更具可读性和可维护性。
答案 2 :(得分:6)
应该避免模仿经典OO并使用原型OO代替。一个很好的原型OO实用程序库是traits。
而不是覆盖方法和设置继承链(一个应该总是支持对象组合而不是对象继承),你应该将可重用的函数捆绑到特征中并用这些创建对象。
var modifyA = {
modify: function() {
this.x = 300;
this.y = 400;
}
};
var modifyB = {
modify: function() {
this.x = 3000;
this.y = 4000;
}
};
C = function(trait) {
var o = Object.create(Object.prototype, Trait(trait));
o.modify();
console.log("sum : " + (o.x + o.y));
return o;
}
//C(modifyA);
C(modifyB);
答案 3 :(得分:3)
modify()是一个私有函数,无法从A,B或C定义中的任何位置访问。您需要将其声明为
this.modify = function(){}
C没有引用它的父项,除非你把它传递给C.如果C被设置为继承自A或B,它将继承它的公共方法(不是它的私有函数,就像你定义了modify())。一旦C从其父级继承方法,您就可以覆盖继承的方法。
答案 4 :(得分:2)
您在上一次调用的方法modify()
在全局上下文中调用
如果您要覆盖modify()
,首先必须继承A
或B
。
也许你正试图这样做:
在这种情况下,C
会继承A
function A() {
this.modify = function() {
alert("in A");
}
}
function B() {
this.modify = function() {
alert("in B");
}
}
C = function() {
this.modify = function() {
alert("in C");
};
C.prototype.modify(); // you can call this method where you need to call modify of the parent class
}
C.prototype = new A();
答案 5 :(得分:1)
除非您将所有变量设为“公开”,即直接或通过Function
属性使其成为prototype
的成员。
var C = function( ) {
this.x = 10 , this.y = 20 ;
this.modify = function( ) {
this.x = 30 , this.y = 40 ;
console.log("(!) C >> " + (this.x + this.y) ) ;
} ;
} ;
var A = function( ) {
this.modify = function( ) {
this.x = 300 , this.y = 400 ;
console.log("(!) A >> " + (this.x + this.y) ) ;
} ;
} ;
A.prototype = new C ;
var B = function( ) {
this.modify = function( ) {
this.x = 3000 , this.y = 4000 ;
console.log("(!) B >> " + (this.x + this.y) ) ;
} ;
} ;
new C( ).modify( ) ;
new A( ).modify( ) ;
new B( ).modify( ) ;
您会注意到一些变化。
最重要的是,对所谓的“超类”构造函数的调用现在隐含在这一行中:
<name>.prototype = new C ;
A
和B
现在都有可单独修改的成员x
和y
如果我们写完就不会出现这种情况而是... = C
。
然后,x
,y
和modify
都是“公开”成员,因此为他们分配不同的Function
<name>.prototype.modify = function( ) { /* ... */ }
将“覆盖”该名称的原始Function
。
最后,对modify
的调用无法在Function
声明中完成,因为当我们设置所谓的“超类”时,将再次执行对“超类”的隐式调用。到所谓的“子类”的prototype
属性。
但是,这或多或少是你在JavaScript中做这种事情的方式。
HTH,
FK
答案 6 :(得分:0)
function A() {
var c = new C();
c.modify = function(){
c.x = 123;
c.y = 333;
}
c.sum();
}
function B() {
var c = new C();
c.modify = function(){
c.x = 999;
c.y = 333;
}
c.sum();
}
C = function () {
this.x = 10;
this.y = 20;
this.modify = function() {
this.x = 30;
this.y = 40;
};
this.sum = function(){
this.modify();
console.log("The sum is: " + (this.x+this.y));
}
}
A();
B();
&#13;