我害怕提出这个问题,因为在同一主题上有这么多人。
我想了解使用call
和approach-1
简单继承
approach-2
答案 0 :(得分:1)
在基于原型的语言中,继承是通过克隆作为原型而不是类的现有对象来执行的。
因此,在每种情况下,我们都应该考虑选择用作原型来确定行为的对象。
在方法1中,您将Student
的原型设置为与Person
相同的原型对象。这意味着对Student.prototype
所做的任何更改都会影响Person.prototype
,反之亦然。
在方法2中,您将Student
的原型设置为新的Person对象,该对象将根据您的初始化代码设置{name: 'de-name', age: 0}
以下属性。然后,您通过调用Person.call()
函数中的Student
来覆盖名称属性。由于这是一个全新的对象,对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()
允许您执行differential inheritance之外,您与Object.create
几乎完全相同。您甚至可以添加其他属性作为其第二个参数:
Student.prototype = Object.create(Person.prototype, {
age: 16,
study: function() { console.log("But I'm sooo lazy!!!"); }
});
答案 1 :(得分:0)
方法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.
因此,您不将其分配给学生原型,将其分配给学生本身,并且学生将Person作为其原型。
答案 2 :(得分:0)
approach-2表示原型链中的另一个对象。如果(new Student()).someAttr
在学生对象(new Student()
)中没有解决,则使用方法2,检查人物对象(new Person()
)(因为那是' s&# 39; s在Student.prototype
),然后是Person.prototype
。使用方法1,没有人对象。