继承的Javascript对象丢失属性值

时间:2016-04-01 16:00:00

标签: javascript factory-pattern abstraction prototypal-inheritance

我试图创建一个javascript工厂模式示例,该示例利用原型继承使用原型继承,但控制台日志中的值未定义。

var AthleteFactory = function() {
    var athlete, that = this;

    this.createAthlete = function(athleteType, athleteName, athleteCountry, athleteUnit) {
        switch (athleteType) {
            case "Swimmer":
                athlete = new Swimmer(athleteName, athleteCountry, athleteUnit);
                break;
            case "Runner":
                athlete = new Runner(athleteName, athleteCountry, athleteUnit);
                break;
        }

        return athlete;
    }
};

下面是构造函数:

function Athlete(theName, theCountry, theUnit) {
    this.name = theName;
    this.country = theCountry;
    this.distance = 0;
    this.unit = theUnit;
};

运动员对象(抽象/基础对象)

Athlete.prototype = {
    constructor: Athlete,
    recordDistance: function(distance) {
        this.distance += distance;
    },
    showProgress: function() {
        $("#output").append("<h1>" + this.name + " of " + this.country + " has achieved: " + this.distance + this.unit + "</h1>");
    },
};

扩展运动员基础对象

var Swimmer = function(theName, theCountry, theUnit) {};
Swimmer.prototype = new Athlete();
Swimmer.prototype.DoExercise = function(difficulty) {
    switch (difficulty) {
        case "easy":
            this.recordDistance(20);
            break;
        case "moderate":
            this.recordDistance(50);
            break;
        case "hard":
            this.recordDistance(100);
            break;
    };
};

DoExercise包含逻辑差异,因此包含工厂模式

var Runner = function(theName, theCountry, theUnit) {};
Runner.prototype = new Athlete();
Runner.prototype.DoExercise = function(difficulty) {
    switch (difficulty) {
        case "easy":
            this.recordDistance(5);
            break;
        case "moderate":
            this.recordDistance(20);
            break;
        case "hard":
            this.recordDistance(60);
            break;
    };
};
//create some athletes in our factory
var factory = new AthleteFactory();

var phelps = factory.createAthlete("Swimmer", "Micheal Phelps", "USA", "Metres");
console.log(phelps);

var farah = factory.createAthlete("Runner", "Mo Farah", "UK", "Kilometres");
console.log(farah);

phelps.DoExercise("easy");
phelps.DoExercise("moderate");
phelps.DoExercise("hard");
phelps.showProgress(); //undefined of undefined has achieved: 170undefined

farah.DoExercise("moderate");
farah.DoExercise("easy");
farah.DoExercise("hard");
farah.showProgress(); //undefined of undefined has achieved: 85undefined

我来自C#背景而不是Javascript,所以我可能会误解一两个基本的差异。虽然我可以创建单独的函数来实现相同的任务,但最好能让它工作,

这是codepen链接: http://codepen.io/paulcthomas/pen/aNLJyq?editors=1010

2 个答案:

答案 0 :(得分:0)

在你的Swimmer和Runner构造函数中,你必须像这样调用基类的构造函数:

var Swimmer = function(theName, theCountry, theUnit) { 
    Athlete.call(this, theName, theCountry, theUnit);
};

答案 1 :(得分:0)

您真正想要的是继承子类中的构造函数。这不会在JS中自动发生。您必须在子类构造函数中手动调用父类构造函数。

正如您在使用相同模式的this article中所看到的,一般解决方案就是这样。

document.body.style.backgroundImage = "url('image.png')";

此时,如果不是为了更容易阅读,您也无法在子类构造函数中定义参数

var Swimmer = function(theName, theCountry, theUnit) { 
    Athlete.apply(this, arguments)
};
  

当内在时,会自动调用超类构造函数。   首先继承,然后做某事,没有非丑陋的方式   调用超类构造函数。