我正在尝试通过添加继承来掌握模块模式。我来自大学背景,主要是Java,但我已经使用网络技术大约十年了。我只用了大约一年的JavaScript ...
无论如何,我正在尝试一个简单的继承(.prototype
)示例。在People
对象中,您可以添加Gentleman
,然后使用.toString()
方法列出它们。 Gentleman
是Human
的孩子。它实现了“抽象”Human
,但现在代码不会运行。
请评论我的代码被认为是坏的。我想继续使用模块/原型方法,但我做错了什么?我也会听取this
在不同背景下的含义。即,People
我可以直接使用私有_people
,但在子模块中我必须使用this._name
- 为什么?
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领域的简单教程。
答案 0 :(得分: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()
调用添加属性。 see reference
至于this
:
您可以直接使用_people
,因为它是一个变量。 People
的所有实例都拥有相同的人员列表。
当您将函数作为对象的方法调用时,this
引用对象本身。由于每个Human
都应该有自己的名称,this._name
引用this
^^ human的名称。因此aGentleman.toString()
会返回this
绅士的名字。
People.Human = (function () {
this._name; //<- does not do anything.
答案 1 :(得分: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 } }
});