Jul*_*les 6 javascript inheritance prototype prototypal-inheritance
我认为差异已经在我的脑海中点击,但我想确定.
他说,在道格拉斯克罗克福德页面上的JavaScript Prototypal Inheritance中
在原型系统中,对象从对象继承.但是,JavaScript缺少执行该操作的运算符.相反,它有一个新的运算符,这样new f()就会产生一个从f.prototype继承的新对象.
我真的不明白他在那句话中想说的是什么,所以我进行了一些测试.在我看来,关键的区别在于,如果我在纯原型系统中基于另一个对象创建一个对象,那么所有父父成员应该在新对象的原型上,而不是在新对象本身上.
这是测试:
var Person = function(name, age) {
this.name = name;
this.age = age;
}
Person.prototype.toString = function(){return this.name + ', ' + this.age};
// The old way...
var jim = new Person("Jim",13);
for (n in jim) {
if (jim.hasOwnProperty(n)) {
console.log(n);
}
}
// This will output 'name' and 'age'.
// The pure way...
var tim = Object.create(new Person("Tim",14));
for (n in tim) {
if (tim.hasOwnProperty(n)) {
console.log(n);
}
}
// This will output nothing because all the members belong to the prototype.
// If I remove the hasOwnProperty check then 'name' and 'age' will be output.
Run Code Online (Sandbox Code Playgroud)
我的理解是否正确,在测试对象本身的成员时,差异才会变得明显?
您的假设是正确的,但是道格拉斯没有过多谈论另一种模式 - 原型也可以用于属性。你的 person 类可以写成:
var Person = function(name, age) {
this.name = name;
this.age = age;
}
Person.prototype.name = null; //default value if you don't init in ctor
Person.prototype.age = null;
Person.prototype.gender = "male";
Person.prototype.toString = function(){return this.name + ', ' + this.age;};
Run Code Online (Sandbox Code Playgroud)
在这种情况下,如您在示例中所做的那样,迭代此类实例的属性将不会生成“性别”属性的输出。
编辑1:构造函数中名称和年龄的分配确实使属性通过 hasOwnProperty 可见(感谢@matt提醒我这一点)。未分配的性别属性将不可见,直到有人在实例上设置它。
编辑 2:为了进一步补充这一点,我提出了一种替代继承模式 - 我个人在非常大的项目中使用过的模式:
var inherits = function(childCtor, parentCtor) {
function tempCtor() {};
tempCtor.prototype = parentCtor.prototype;
childCtor.superclass = parentCtor.prototype;
childCtor.prototype = new tempCtor();
childCtor.prototype.constructor = childCtor;
};
var Person = function(name){
this.name = name;
}
Person.prototype.name = "";
Person.prototype.toString = function(){
return "My name is " + this.name;
}
var OldPerson = function(name, age){
OldPerson.superclass.constructor.call(this);
this.age = age
};
inherits(OldPerson, Person);
OldPerson.prototype.age = 0;
OldPerson.prototype.toString = function(){
var oldString = OldPerson.superclass.toString.call(this);
return oldString + " and my age is " + this.age;
}
Run Code Online (Sandbox Code Playgroud)
这是一种相当常见的模式,但有一点小小的不同——父类通过“超类”属性附加到子类,允许您访问被子类覆盖的方法/属性。从技术上讲,您可以替换OldPerson.superclass为Person,但这并不理想。如果您曾经将 OldPerson 更改为从 Person 以外的类继承,则还必须更新对 Person 的所有引用。
编辑3:为了完成这个完整的循环,这里是“继承”函数的一个版本,它利用了 Object.create ,其功能与我之前描述的完全相同:
var inherits = function(childCtor, parentCtor) {
childCtor.prototype = Object.create(parentCtor.prototype);
childCtor.superclass = parentCtor.prototype;
};
Run Code Online (Sandbox Code Playgroud)