8. 原型和继承
- 原型和原型链分别是什么?描述 JavaScript 内置的原型链。
a . 原型 :JavaScript
中我们每创建一个函数都有prototype(原型)
属性,指向原型对象,原型对象的用途是包含可以特定类型的所有实例共享的属性和方法。
b. 原型链
- 描述实例,构造函数,原型的联系。
- 每一个构造函数都拥有一个
prototype
属性,这个属性指向一个对象,也就是原型对象 - 原型对象默认拥有一个
constructor
属性,指向它的那莪构造函数 - 每个对象都拥有一个隐藏属性
__prototype__
,指向它的原型对象 ```javascript function Person() {}
- 每一个构造函数都拥有一个
let person = new Person();
person.proto === Person.prototype //true
Person.prototype.constructor === Person //true
**原型特点 : **
- 实例可以共享原型上面的属性和方法
- 实例调用属性会先从自身找,若自身没有才会去原型上面找
3. 罗列各种实现继承的方式,并用代码展示。
- 原型链继承
```javascript
function Parent() {
this.name = "Parent";
}
Parent.prototype.sayHi = function() {
console.log('Hi !!!');
}
function Child() {
this.name = 'Child';
}
Child.prototype = new Parent();
let c1 = new Child();
console.log(c1);
- 寄生式继承
寄生式继承就是用一个函数包装一个对象,然后返回这个函数的调用,这个函数就变成了个可以随意增添属性的实例或对象。 ```javascript function object(obj) { let clone = Object(obj); clone.sayHi = function() {
} return clone; }console.log("Hi !!!");
let sub = { name:’sub’ } let sup = object(sub); console.log(sup);
- 盗用构造函数<br />在字类构造函数中调用父类构造函数。我们可以用`.call()`和`.apply()`将父类构造函数引入子类函数。
```javascript
function SuperType() {
this.names = ["jackson", "bear"];
}
function SubType() {
// 继承 SuperType
SuperType.call(this);
}
let instance1 = new SubType();
instance1.names.push("daxiong");
console.log(instance1.names); // ["jackson", "bear", "daxiong"]
let instance2 = new SubType();
console.log(instance2.names); // ["jackson", "bear"]
- 组合继承
组合继承(经典继承)综合了原型链和盗用构造函数,将两者的优点集中起来,基本的思路就是使用原型链继承原型上的属性和方法,而通过盗用构造函数继承实例属性,这样既可以吧方法定义在原型上以实现重用,又可以让每个实例都有自己的属性,
function SuperType(name) {
this.name = name;
this.colors = ['red','blue','grenn'];
}
SuperType.prototype.sayName = function() {
console.log(this.name);
}
function SubType(name,age) {
SuperType.call(this,name);
this.age = age;
}
SubType.prototype = new SuperType();
SubType.prototype.constructor = SubType;
SubType.prototype.sayAge = function(){
console.log(this.age);
}
console.log(new SubType());
- 寄生式组合继承
寄生式组合继承通过调用构造函数继承属性,但是用混合式原型链的集成方法,但基本思路是不通过调用父类构造函数给子类原型赋值,而是取得父类原型的一个副本,说到底就是使用寄生式来继承父类原型,然后将返回的新对象赋值给子类对象
function inheritPrototype(SubType,SuperType) {
let prototype = Object(SuperType.prototype) //创建对象
prototype.constructor = SubType; //增强对象
SubType.prototype = prototype; //赋值对象
}
/*
这个函数接收两个参数(子类构造函数,父类构造函数),在这个函数内部,
第一步是父类原型的一个副本,然后,给返回的prototype对象设置constrcutor
属性,解决了由于重写类型导致的默认constructor丢失问题,最后将创建
的对象赋值给子类型的原型
*/
function SuperType(name) {
this.name = name;
this.colors = ['red','green'];
}
SuperType.prototype.sayName = function() {
console.log(this.name);
}
function SubType(name,age) {
SuperType.call(this,name);
this.age = age
}
inheritPrototype(SubType,SuperType);
console.log(new SubType('wbt',19));