0

我试图通过增加继承来掌握模块模式。我来自大学背景,我的后备箱中主要使用 Java,但我已经使用 Web 技术大约十年了。不过,我对 JavaScript 的了解只有一年左右......

无论如何,我正在尝试一个简单的继承 ( .prototype) 示例。从People对象中,您可以添加Gentleman',然后使用它们的.toString()方法列出它们。AGentleman是 a 的孩子Human。在我实现“抽象”之前一切顺利Human,但现在代码将无法运行。

请评论我的代码认为不好的地方。我想继续使用模块/原型方法,但我做错了什么?我也会听听this不同情况下的含义。即,People我可以_people直接使用私有,但在子模块中我必须使用this._name--why?

var People = People || {};

People = (function() {
    var People = function(){
        this._people = [];
    };

    var addGentleman = function (name) {
        this._people.push(new People.Gentleman(name));
    };

    var getList = function () {
        var temp = [];

        for (var i = 0; i < this._people.length; i++) {
            temp.push(this._people[i].toString());
        }

        return temp;
    };

    People.prototype.constructor = People;
    People.prototype.addGentleman = addGentleman;
    People.prototype.getList = getList;

    return People;
})();

People.Human = (function () {
    var Human = function (name, hasLadyParts) {
        this._name = name;
        this._hasLadyParts = hasLadyParts;
    };

    var hasLadyParts = function () {
        return this._hasLadyParts;
    };

    var toString = function () {
        var str = this._name;
        if (!this._hasLadyParts) str += ' no';
        return str + ' lady parts.';
    };

    Human.prototype.constructor = Human;
    Human.prototype.hasLadyParts = hasLadyParts;
    Human.prototype.toString = toString;

    return Human;
})();

People.Gentleman = (function () {
    var Gentleman = function (name) {
        People.Human.call(this, name, false);
    }

    var toString = function () {
        return 'Mr.' + People.Human.toString();
    };

    // Gentleman.prototype = Object.create(People.Human.prototype);
    Gentleman.prototype.constructor = Gentleman;
    Gentleman.prototype.toString = toString;

    return Gentleman;
})();

$(function () {
    var people = new People();
    people.addGentleman('Viktor');
    people.addGentleman('Joakim');
    var list = people.getList();
    var $ul = $('#people');

    for (var i = 0; i < list.length; i++) {
        $ul.append('<li>' + list[i] + '</li>');
    }
});

小提琴:http: //jsfiddle.net/5CmMd/5/

编辑:我已经更新了代码并稍微摆弄了一下。如果我得到这个工作,我想我理解了大部分的设计。我认为,这个示例也可以作为未来 OOP 程序员访问 JavaScript 领域的简单教程。

4

2 回答 2

2
Gentleman.prototype = Object.create(People.Human.prototype);

Gentleman.prototype = {
    constructor = Gentleman,
    toString = toString
};

应该是constructor: Gentleman, ...。此外,您分配给prototype两次,因此覆盖它。Gentleman这具有不再继承自的副作用Human。你必须添加到它:

Gentleman.prototype.toString = toString;

Object.create()或者您通过调用添加属性。见参考

至于this

你可以_people直接使用,因为它是一个变量。所有实例People共享相同的人员列表。

当您将函数作为对象的方法调用时,this指的是对象本身。既然每个人都Human应该有自己的名字this._name指的是this^^人类的名字。所以aGentleman.toString()会返回确切this绅士的名字。

People.Human = (function () {
  this._name; //<- does not do anything.
于 2013-05-03T20:24:08.173 回答
1

我认为主要问题在于绅士的原型。对于一个您正在覆盖您从 Human 继承的原型,对于另一个您使用 = 而不是 : 来分配功能:)

尝试这个:

    var People = People || {};

People = (function() {
    var _people = [];

    var People = function(){};

    var addGentleman = function (name) {
        _people.push(new People.Gentleman(name));
    };

    var getList = function () {
        var temp = [];

        for (var i = 0; i < _people.length; i++) {
            temp.push(_people[i].toString());
        }

        return temp;
    };

    People.prototype = {
        constructor: People,
        addGentleman: addGentleman,
        getList: getList
    };

    return People;
})();

People.Human = (function () {
    this._name;

    var Human = function (name) {
        this._name = name;
    };



    Human.prototype = {
        constructor: Human,
    };

    return Human;
})();

People.Gentleman = (function () {

    var Gentleman = function (name) {
        People.Human.call(this, name);     
    }

    var toString = function () {
        return 'Mr. ' + this._name;
    };

   Gentleman.prototype = Object.create(People.Human.prototype);


    Gentleman.prototype.constructor = Gentleman;
    Gentleman.prototype.toString = toString;

    return Gentleman;
})();

$(function () {
    var people = new People();
    people.addGentleman('Viktor'); // this is me
    people.addGentleman('Joakim'); // and my friend!
    var list = people.getList();
    var $ul = $('#people');

    for (var i = 0; i < list.length; i++) {
        $ul.append('<li>' + list[i] + '</li>');
    }
});

您可以看到我已将新的 toString 方法添加到原型对象,而不是覆盖已经存在的内容。我不知道该模式是否有更好的方法来做到这一点(我不熟悉它)。

如果看起来更合适,您可以这样做:

Gentleman.prototype = Object.create(People.Human.prototype, 
{ 
    constructor : { configurable: true, get : function() { return Gentleman } }, 
    toString : { configurable: true, get : function() { return toString } }
});
于 2013-05-03T20:23:59.010 回答