1.原型链继承:将父亲的实例赋给子类的原型。
缺点:如果有一个子类实例改变所继承的内容,则当下一个子类实例继承是会是上一个子类改变之后的内容,而不是原有父亲的内容。
(解决:对象冒充继承方法)
function Father(name, age) { this.name = 'li'; this.age = 3; this.arr = [1, 2, 3]; } function Son(sex) { this.sex = sex; } Son.prototype = new Father; //将父类的实例赋值给子类的原型 var son1 = new Son('男'); //new一个子类的实例son1 var son2 = new Son('女'); //new一个子类的实例son2 console.log(son1.arr); //打印son1继承的属性arr [1, 2, 3] son1.arr.push(4); //通过son1改变arr的值 此时改变的是子类的原型链 console.log(son2.arr); //再用son2打印arr值 [1, 2, 3, 4]
优点: 解决了原型链继承引用类型共用的问题 。
缺点:不能调用父类原型链中的方法函数。(解决:组合模式方法)
function Father(name, age) { this.name = 'li'; this.age = 3; this.arr = [1, 2, 3]; this.sayHi = function() { return 'Hi' + this.name; } } Father.prototype.showName = function() { return this.name; } function Son(sex) { Father.call(this); //通过call改变Father的this指向Son,这样就可以使Son中拥有Father的属性 this.sex = sex; } var son1 = new Son('男'); console.log(son1); //Son {nme: "li", age: 3, arr: Array(3), sex: "男", sayHi: ƒ} console.log(son1.name); //li console.log(son1.sayHi()); //可以调用父类本身具有的方法 Hili // console.log(son1.showName()); //报错 son1.showName is not a function //缺点:不能调用父类原型链中的方法函数 //---------------------------------------------------------- //解决了原型链中一个子类对象改变父类属性会影响其他子类的问题 son1.arr.push(4); console.log(son1.arr); //[1, 2, 3, 4] var son2 = new Son(); console.log(son2.arr); //[1, 2, 3]
优点:解决了不能调用父类原型链中的方法函数;
缺点: 1.相同的属性,在原型链上出现了两次(读取没有问题,因为子实例上面的屏闭了 原型上面的属性)
2.父类的构造函数调用了两次
解决:寄生组合继承
function Father(name, age) { this.name = 'li'; this.age = 3; this.arr = [1, 2, 3]; this.sayHi = function() { return 'Hi' + this.name; } } Father.prototype.showName = function() { return this.name; } function Son(sex) { Father.call(this); //通过call改变Father的this指向Son,这样就可以使Son中拥有Father的属性 调用一次 this.sex = sex; } Son.prototype = new Father(); //通过原型链继承父类原型中的方法 调用两次 var son1 = new Son('男'); console.log(son1); //Son {name: "li", age: 3, arr: Array(3), sex: "男", sayHi: ƒ} console.log(son1.showName()); //li console.log(son1.sayHi()); //Hili
可以看到age,arr,name,sayHi在原型链中出现了两次。
function Father(name, age) { this.name = 'li'; this.age = 3; this.arr = [1, 2, 3]; this.sayHi = function() { return 'Hi' + this.name; } } Father.prototype.showName = function() { return this.name; } // Son.prototype = new Father;//不能直接继承父类 // 父的实例,不能直接赋给子的原型,利用一个中间函数中转一下 function Son(sex) { Father.call(this); // 利用对象冒充继承继承属性Father的属性 this.sex = sex; } // var F = function() {}; // F.prototype = Father.prototype; // Son.prototype = new F(); // Son.prototype.constructor = Son; inherits(Son, Father); // 调这个封装函数,相当于上面四句话 // 子的原型上的方法,必须在调用inherits以后,再添加 var son1 = new Son('男'); console.log(son1.showName()); //li function inherits(Child, Parent) { var F = function() {}; F.prototype = Parent.prototype; Child.prototype = new F(); Child.prototype.constructor = Child; }