原型链
通过原型链继承:Child.prototype = new Father(); // Child.prototype.__proto__ === Father.prototype
- 缺点:
- 原型链中的引用类型会被所有实例共享
- 无法向父级构造函数传参 ```javascript // Father.proto === Function.prototype // Father.prototype.proto === Object.prototype function Father(){ } Father.prototype.name = “baba”;
Child.prototype = new Father(); // Child.prototype.proto === Father.prototype
function Child(){
}
var child = new Child();
console.log(child.name); // “baba”
<a name="tGYtP"></a>
### 借用构造函数
在子构造函数中通过 call()、apply() 调用父级造函数,可以向父级构造函数传参<br />缺点:每个实例都创建了共有属性的副本,破坏了代码的复用性,浪费空间
```javascript
function Father(name) {
this.name = name;
}
function Child(name) {
Father.call(this, name);
}
var child1 = new Child("baba");
var child2 = new Child("mama");
console.log(child1.name); // "baba"
console.log(child2.name); // "mama"
child2.name = "me"
console.log(child1.name); // "baba"
console.log(child2.name); // "me"
组合继承
原型链 + 借用构造函数,共享属性用原型链继承,非共享属性借用父级构造函数
缺点:需要调用两次父级构造函数,耗内存
function Father(name) {
this.name = name;
}
Father.prototype.getName = function() {
console.log(this.name); // 共享属性通过原型链继承
}
function Child(name) {
Father.call(this, name); // 非共享属性借用父级构造函数
}
Child.prototype = new Father(); // 与寄生组合继承不同之处
Child.prototype.constructor = Child; // Child.prototype.__proto__ === Father.prototype
var child1 = new Child("baba");
var child2 = new Child("mama");
child1.getName(); // "baba"
child2.getName(); // "mama"
child2.name = "me";
child1.getName(); // "baba"
child2.getName(); "me"
原型式继承
// 以 obj 作为原型构建对象
function creatObject(obj) {
function F(){};
F.prototype = obj;
return new F();
}
var parent = {
name: "baba"
}
var child = creatObject(parent);
console.log(child.name); // "baba"
该方法类似通过 Object.create() 创建对象
// 创建对象:Object.create(原型)
var person = Object.create(Person.prototype);
var obj = Object.create(null); //创建没有原型的对
寄生继承
function object(obj) {
var clone = Object.create(obj);
clone.sayHi = function(){
console.log("Hi " + this.name);
}
return clone;
}
var parent = {
name: "baba"
}
var child1 = object(parent);
var child2 = object(parent);
console.log(child1.sayHi === child2.sayHi); // false
寄生组合式继承
组合继承改进版,不需要调用两次父级构造函数
function Parent(name) {
this.name = name;
}
Parent.prototype.getName = function() {
console.log(this.name);
}
function Child(name) {
Parent.call(this, name);
}
function inheritPrototype(Parent, Child) {
Child.prototype = Object.create(Parent.prototype); // 与组合继承不同之处
Child.prototype.constructor = Child;
}
inheritPrototype(Parent, Child);
var child = new Child('baba');
child.getName(); // "baba"
圣杯模式
function inherit(Target, Origin) {
function F() {};
F.prototype = Origin.prototype;
Target.prototype = new F();
Target.prototype.constructor = Target;
Target.prototype.uber = Origin.prototype; // 记录继承原型
}
var inherit = (function() {
function F() {};
return function(Target, Origin) {
F.prototype = Origin.prototype;
Terget.prototype = new F();
Terget.prototype.constructor = Target;
Target.prototype.uber = Origin.prototype;
}
}());
Class 继承
ES6 extends 继承,与 java 类似
class Parent{
constructor(name){
this.name = name;
}
getName(){
console.log(this.name);
}
}
class Child extends Parent{
constructor(name, age){
super(name);
this.age = age;
}
getAge(){
console.log(this.age);
}
}
let child = new Child("baba", 18);
child.getName(); // "baba"
child.getAge(); // 18