在Javascript(ES5)中尝试简单的OPP继承方法

adr*_*eld 5 javascript oop inheritance prototype

只是为了好奇,我在Javascript中玩原型继承和OOP继承.大多数结果涉及使用函数模拟"类"和"扩展"概念,而其他结果则使用原型和构造函数.

我写了这段代码:

function Warrior(weaponName) {
    var weapon = weaponName;
    this.getWeapon = function() {
        return weapon;
    };
    this.setWeapon = function(value) {
        weapon = value;
    };
    this.displayInfo = function() {
        return {
            "weapon": this.getWeapon(),
        };
    };
}

function Archer() {
    var accuracy = "86%";
    this.parent = Archer.prototype; // Inheritance workaround
    this.getAccuracy = function() {
        return accuracy;
    };
    this.setAccuracy = function(value) {
        accuracy = value;
    };
    this.displayInfo = function() {
        var form = this.parent.displayInfo();
        form.accuracy = this.getAccuracy();
        return form;
    };
}
Archer.prototype = new Warrior("bow");
var w = new Warrior("sword");
var a = new Archer();
console.log(w.displayInfo());
console.log(a.displayInfo());
Run Code Online (Sandbox Code Playgroud)

我这样做是为了在显示来自Warrior类的信息时,它将对象显示为

{ weapon: "sword" }
Run Code Online (Sandbox Code Playgroud)

当显示来自Archer的信息时,对象是:

{ weapon: "sword", accuracy: "86%" }
Run Code Online (Sandbox Code Playgroud)

"子类"从"超类"中获取信息并添加到其中.从Archer调用"getWeapon()"或"setWeapon"也有效.即使我添加第三类"Kyudoka",扩展"Archer"并拥有它自己的属性,这个链也没有问题.

但是与我在研究时发现的更复杂的代码相比,我觉得这可能是一个天真的实现("继承工作方式"行),我缺少一些东西(考虑到JS有很多细微之处).

这是一个理论问题,我没有在任何系统中使用此代码.

Rog*_*ger 2

根据《Javascript the Good Parts》一书的说法, javascript中的继承主要有3种:伪经典继承原型继承函数式继承。

您刚刚发布的内容适合伪经典继承,您可以在其中使用构造函数模拟类行为。

我发现函数式模式更有用、更灵活,它允许您保护变量(使它们私有)。

var constructor = function (spec, my) {
  var that, other private instance variables;
  my = my || {};
  //Add shared variables and functions to my
  that = a new object;
  //Add privileged methods to that
  return that;
}
Run Code Online (Sandbox Code Playgroud)

原型基本上是让您的对象直接从其他有用的对象继承,这就像将它们(有用的对象)作为您的新对象构造函数原型。

Object.beget = function (o) {
  var F = function () {};
  F.prototype = o;
  return new F();
};

var a = {}
//Add shared variables to a
var b = Object.beget(a);
//Add new methods to b
Run Code Online (Sandbox Code Playgroud)

每个模式都有很多考虑因素,例如 Crockford 在他的书中说道“函数式模式具有很大的灵活性。它比伪经典模式需要更少的工作,并且为我们提供了更好的封装和信息隐藏以及对超级方法的访问”。,但我也看到过一些文章以相反的方式争论,例如这个http://bolinfest.com/javascript/inheritance.php

编辑 - - -

如果您可能想了解访问超级方法的不同方法,在功能模式中您可以执行以下操作:

Function.prototype.method = function (name, func) {
  this.prototype[name] = func;
  return this;
};

Object.method('superior', function (name) {
  var that = this,
  method = that[name];
  return function ( ) {
    return method.apply(that, arguments);
  };
});

var archer = function (spec, accuracy) {
  var that = warrior(spec),
  super_displayInfo = that.superior('displayInfo');
  that.getAccuracy = function() {
    return accuracy;
  };
  that.setAccuracy = function(value) {
    accuracy = value;
  };
  that.displayInfo = function (n) {
    var form = super_displayInfo()
    form.accuracy = that.getAccuracy();
    return form;
  };
  return that;
};
Run Code Online (Sandbox Code Playgroud)