JavaScript覆盖方法

Dan*_*ase 73 javascript oop overriding

假设你有以下代码:

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));
}
Run Code Online (Sandbox Code Playgroud)

现在的问题是,如果有任何方法,我可以modify使用A和B中的方法覆盖C中的方法.在Java中,您将使用super关键字,但是如何在JavaScript中实现类似的功能呢?

Ada*_*dam 128

编辑:现在已经六年了,原来的答案已经写好了,而且很多都改变了!

  • 如果您使用的是较新版本的JavaScript,可能使用像Babel这样的工具进行编译,那么您可以使用真正的类.
  • 如果您正在使用AngularReact提供的类类组件构造函数,那么您将需要查看该框架的文档.
  • 如果你正在使用ES5并使用原型手工制作"假"类,下面的答案仍然是正确的.

祝好运!


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"
Run Code Online (Sandbox Code Playgroud)

不幸的是,这有点难看,它不包括一个非常好的"超级"方法:你必须手动指定你想要调用哪些父类的方法.因此,有许多工具可以使创建类更好.尝试查看Prototype.js,Backbone.js或类似的库,其中包含用于在js中执行OOP的更好的语法.

  • 我相信而不是Car.prototype = new Vehicle(); 这应该是Car.prototype = Object.create(Vehicle.prototype); 没有? (9认同)
  • 或者使用工具"使创建类更好",你根本无法创建类.js中的经典OO仿真总是变得混乱. (2认同)

Yot*_*fek 43

由于这是谷歌的热门话题,我想提供一个更新的答案.

使用ES6类使继承和方法覆盖更容易:

'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
Run Code Online (Sandbox Code Playgroud)

在继承类中使用时,super关键字引用父类.此外,父类的所有方法都绑定到子实例,因此您不必编写super.method.apply(this);.

至于兼容性:ES6兼容性表仅显示主要播放器支持类的最新版本(主要是).V8浏览器从今年1月开始就已经有了它们(Chrome和Opera),使用SpiderMonkey JS引擎的Firefox将在下个月推出官方Firefox 45版本.在移动端,Android仍然不支持此功能,而五个月前发布的iOS 9部分支持.

幸运的是,Babel是一个JS库,用于将Harmony代码重新编译为ES5代码.ES6中的类和许多其他很酷的功能可以使您的Javascript代码更具可读性和可维护性.

  • 这个答案值得更多的信任,目前是正确的答案. (7认同)

Ray*_*nos 5

应该避免模仿经典OO并使用原型OO.适用于原型OO的优秀实用程序库是特征.

而不是覆盖方法和设置继承链(一个应该始终支持对象组合而不是对象继承),您应该将可重用的函数捆绑到特征中并使用这些特性创建对象.

实例

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);
Run Code Online (Sandbox Code Playgroud)

  • 你没有回答这个问题.如果有的话,这应该是评论. (9认同)