JavaScript 覆盖方法

IT技术 javascript oop overriding
2021-03-17 16:45:17

假设您有以下代码:

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));
}

现在的问题是,如果有任何方式,我可以覆盖的方法modify,从C与在方法AB在 Java 中,您会使用super-keyword,但是如何在 JavaScript 中实现这样的功能呢?

6个回答

编辑:距离最初的答案已经写了六年,而且已经发生了很多变化!

  • 如果您使用的是较新版本的 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"

不幸的是,这有点难看,它没有包含一个非常好的“超级”方法:您必须手动指定要调用的父类的方法。因此,有多种工具可以更好地创建类。尝试查看 Prototype.js、Backbone.js 或包含在 js 中执行 OOP 的更好语法的类似库。

Car.prototype = new Vehicle();的原因之一 是不正确的,因为在接收颜色时没有任何东西可以传递给 Vehicle()。
2021-04-27 16:45:17
除了使用工具“使创建类更好”之外,您根本无法创建类。js 中的经典 OO 模拟总是变得混乱。
2021-04-29 16:45:17
我相信而不是 Car.prototype = new Vehicle(); 这应该是 Car.prototype = Object.create(Vehicle.prototype); 不?
2021-05-04 16:45:17
(不是建设性的评论)作为浏览器世界中的“低级”语言毫无理由地非常丑陋。还在学习中,谢谢!
2021-05-16 16:45:17
@Martin 是对的,请参阅javascript-inheritance
2021-05-19 16:45:17

由于这是谷歌上的热门话题,我想给出一个更新的答案。

使用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

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

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

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

这个答案值得更多的赞誉,目前是正确的答案。
2021-04-20 16:45:17
哇!像魅力一样工作!
2021-05-04 16:45:17

曾经应该避免模仿经典的面向对象,而是使用原型面向对象。原型 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);
你不是在回答这个问题。如果有的话,这应该是一个评论。
2021-05-01 16:45:17
2021-05-20 16:45:17

您的示例中的 modify() 是一个私有函数,除了在您的 A、B 或 C 定义中,它不能从任何地方访问。您需要将其声明为

this.modify = function(){}

C 没有对其父项的引用,除非您将其传递给 C。如果 C 设置为从 A 或 B 继承,它将继承其公共方法(而不是像您定义的 modify() 那样的私有函数)。一旦 C 从其父级继承方法,您就可以覆盖继承的方法。

本地/私有,这不是同一回事,只是不同的术语吗?
2021-05-07 16:45:17
modify 是一个本地函数。javascript 中没有私有
2021-05-19 16:45:17

该方法modify(),如果你想越过你在过去被称为被称为在全球范围内modify(),你首先必须继承AB

也许您正在尝试这样做:

在这种情况下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();
C.prototype.modify()会有错误的this值。C.prototype代替c的实例。请使用,.call(this)但您的答案只是重复:)
2021-05-14 16:45:17