Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/378.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在Javascript(ES5)中尝试简单的OPP继承方法_Javascript_Oop_Inheritance_Prototype - Fatal编程技术网

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

在Javascript(ES5)中尝试简单的OPP继承方法,javascript,oop,inheritance,prototype,Javascript,Oop,Inheritance,Prototype,只是出于好奇,我在玩Javascript中的原型继承和OOP继承。大多数结果涉及使用函数模拟“类”和“扩展”概念,而其他结果使用原型和构造函数 我写了这段代码: function Warrior(weaponName) { var weapon = weaponName; this.getWeapon = function() { return weapon; }; this.setWeapon = function(value) {

只是出于好奇,我在玩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());
我在显示Warrior类的信息时这样做的,它将对象显示为

{ weapon: "sword" }
当显示来自Archer的信息时,对象是:

{ weapon: "sword", accuracy: "86%" }
“子类”从“超类”中获取信息并添加到其中。从Archer中调用“Get武器()”或“Set武器”也可以。即使我添加了第三类“Kyudoka”,它扩展了“Archer”并具有自己的属性,该链也不会出现问题

但与我在研究中发现的更复杂的代码相比,我觉得这可能是一个幼稚的实现(“继承解决方案”行),我遗漏了一些东西(考虑到JS有很多微妙之处)


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

将函数放在原型上

function Warrior(weaponName) {
    this.weapon = weaponName;
}

Warrior.prototype = {

    getWeapon : function() {
        return this.weapon;
    },

    setWeapon : function(value) {
        this.weapon = value;
    },

    displayInfo : function() {
        return { "weapon" : this.getWeapon() };
    }
};

//----------------------------------

function Archer(weaponName) {
    Warrior.call(this, weaponName);
    this.accuracy = "86%";
}

Archer.prototype = Object.create(Warrior.prototype);
Archer.prototype.constructor = Archer;

Archer.prototype.getAccuracy = function() {
    return this.accuracy;
};

Archer.prototype.setAccuracy = function(value) {
    this.accuracy = value;
};

Archer.prototype.displayInfo = function() { 
    return "weapon: " + this.getWeapon() + ", accuracy: " + this.getAccuracy();
};


//----------------------------------

var w = new Warrior("sword");
var a = new Archer("axe");
console.log(w.displayInfo()); // Object {weapon: "sword"}
console.log(a.displayInfo()); // weapon: axe, accuracy: 86%

编辑:固定递归

根据《javascript好的部分》一书,javascript中主要有3种继承:伪经典原型函数

您刚刚发布的一个可以放在伪经典继承下,您可以在继承中使用构造函数模拟类行为

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

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

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
每种模式都有很多考虑因素,例如Crockford在他的书中说“功能模式有很大的灵活性,它比伪经典模式需要更少的努力, 并且给了我们更好的封装和信息隐藏,以及对超级方法的访问。”,但我也看到过一些相反的文章,比如

编辑------

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

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

您可以使用
Object.getPrototypeOf(this)
而不是将
Archer.prototype
硬编码为属性。战士的每个实例都创建3个函数。例如,如果你有3个弓箭手,那么它将产生300个功能。通过原型继承,无论有多少实例,您只创建3个函数。我不知道,在这方面可能会有一些优化。这篇文章帮助了我:@WhiteHat-像这样的文章的问题是,它们把它们试图展示给你的东西的本质复杂化了。他展示了太多的概念,不适合做一项敷衍的工作。@LyeFish-谢谢!少硬编码总是好的!您在
Archer
上实现的
displayInfo
创建了无限递归,因为它不调用
武器。displayInfo
@Mike C-很好,我只是复制了操作代码,没有进入minuatia。@数据-感谢您对原型的了解!我知道我可以用我需要的数据覆盖Archers的displayInfo(),但我试图想出一种方法来实际使用“super”方法。但是我会尝试一下Object.create和构造函数,正如您所描述的,看看会发生什么@Adridield-我不会为
super
之类的事情操心,它不适合JS原型结构。您可以创建具有自己属性的对象,并将原型链接到另一个原型。JS只能向下看链,而不能向上看,因此尝试破解超级引用无法实现原型继承/委派的目标。谢谢!事实上,“伪古典”听起来更像是我想要的。我在这个设置中考虑了一些私有变量。默认情况下,我只在“类”中使用“var varable_name”,然后根据需要使用Object、defineProperty/Object、defineProperties getter和setter公开它。我仍然需要对这个想法做更多的修改,我想它不会涵盖“受保护”的变量情况。没问题!如果您感兴趣,我添加了一个不同的解决方法,以达到更好的方法=)
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;
};