[英]Understanding Javascript prototypical inheritance
恐怕要问这个问题,因为在同一主题上已经有很多这样的问题。
我试图了解使用approach-1
和approach-2
缺点/局限性
简单继承
function Person(name, age) { this.name = name || "de-name"; this.age = !!Number(age) ? Number(age) : 0; } Person.prototype.setName = function(name) { this.name = name; return this; } function Student(name) { Person.call(this, name); // Copy instance properties of Person class this.title = "Student"; } // Suggested way Student.prototype = Object.create(Person.prototype); // Possible approach-1 // Student.prototype = Person.prototype; // Possible approach-2 // Student.prototype = new Person();
在基于原型的语言中,继承是通过克隆用作原型而不是具有类的现有对象来执行的。
因此,在每种情况下,我们都应该考虑选择用作原型的对象以确定行为的方式。
在方法1中,您将Student
的原型设置为与Person
相同的原型对象。 这意味着对Student.prototype
所做的任何更改都会影响Person.prototype
,反之亦然。
在方法2中,您将Student
的原型设置为一个新的Person对象,该对象将根据您的初始化代码将以下属性设置为{name: 'de-name', age: 0}
。 然后,您在Student
函数中对Person.call()
调用将覆盖name属性。 由于这是一个全新的对象,因此对Student.prototype
任何修改将仅影响新的Student对象,并且此Person
实例上作为原型的任何缺少的属性都将委派给Person.prototype
。
为了详细说明最后一点(缺少的属性在原型链中传递),下面是一个示例。 假设我们添加一个新的方法greet
来Person
:
Person.prototype.greet = function() { console.log("Hi! " + this.name; ) }
调用new Student().greet()
将使JavaScript在原型链中进行检查,直到遇到适当的属性为止(否则,您将得到未定义的错误。)
// Walking up the chain
/* 1 */ new Student() // doesn't have a greet property
/* 2 */ Student.prototype // => Person {name: 'de-name', age: 0}
// This person instance doesn't have a greet property either
// because we instantiated it before adding the `greet` property
/* 3 */ Person.prototype // Has a greet property which gets called
在Object.create
的建议模式中,您执行的操作与Student.prototype = new Person()
几乎相同,只是Object.create
允许您执行差异继承 。 您甚至可以添加其他属性作为其第二个参数:
Student.prototype = Object.create(Person.prototype, {
age: 16,
study: function() { console.log("But I'm sooo lazy!!!"); }
});
实际上,方法1和方法2并不完全相同。 在方法2中,您将创建一个Person
的新实例,并将该新实例分配给Student的原型。
此外,您应该这样做:
var Student = Object.create(Person.prototype);
根据MDN :
The Object.create() method creates a new object with the specified prototype object and properties.
因此,您无需将其分配给Student原型,而是将其分配给Student本身,然后Student获得Person作为其原型。
Approach-2表示原型链中的另一个对象。 如果(new Student()).someAttr
没有在学生对象( new Student()
)中解析,则采用方法2,将检查人员对象( new Person()
)(因为这是Student.prototype
),然后Person.prototype
。 使用方法1时,没有人对象。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.