Skip to content

Instantly share code, notes, and snippets.

@wenyiweb
Created November 2, 2017 06:24
JavaScript继承方式总结
//javascript的继承方式
/**
简单原型链:
拿父类的实例对象充当子类的原型对象
优点:简单易实现
缺点:1.来自原型对象的引用属性在实例中是共享的
2.无法向父类构造函数传参
*/
function Person() {
this.name = 'parent';
this.arr = [1];
}
Person.prototype.say =function(){
console.log(this.name);
}
function Student(){
}
Student.prototype = new Person();
var s1 = new Student();
var s2 = new Student();
s1.name = 's1';
s1.arr.push(234);
console.log(s1.name);// s1
console.log(s2.name);// parent
console.log(s1.arr);// [1,234]
console.log(s2.arr);// [1,234]
/**
借用构造函数:借父类的构造函数来增强子类实例,等于是把父类的实例属性复制了一份给子类实例装上了
优点:1.解决了子类实例共享父类引用属性的问题;
2.可以向父类传参
缺点:无法实现函数复用,每一个实例都含有一份父类的方法
*/
function Parent(name){
this.name = name || 'parant';
this.arr = [1];
this.say = function () {
console.log(this.name)
}
}
function Child(name){
//核心
Parent.call(this,name);
//...
}
var c1 = new Child('c1');
var c2 = new Child('c2');
c1.name = 'new c1';
c1.arr.push(234);
console.log(c1.name);//"new c1"
console.log(c2.name);//"c2"
console.log(c1.arr);//[1,234]
console.log(c2.arr);//[1]
/**
组合继承:把实例函数都放在原型对象上,以实现函数复用。同时还要保留借用构造函数方式的优点,
通过Super.call(this);继承父类的基本属性和引用属性并保留能传参的优点;
通过Sub.prototype = new Super();继承父类函数,实现函数复用
优点:1.不存在引用属性共享问题
2.可传参
3.方法可复用
缺点:子类原型上有一份多余的父类实例属性,因为父类构造函数被调用了两次,
生成了两份,而子类实例上的那一份屏蔽了子类原型上的。。。内存浪费
*/
function NewParent(name){
//只声明基本属性和引用属性
this.name = name||'parent';
this.arr = [1];
}
//方法都放在原型对象上
NewParent.prototype.say = function(){
console.log(this.name)
}
//NewParent.prototype....
function NewChild(name){
//核心:继承父类的基本属性和引用属性
NewParent.call(this,name);
//...
}
//继承父类函数,实现函数复用
NewChild.prototype = new NewParent();
var nc1 = new NewChild('nc1');
var nc2 = new NewChild('nc2');
nc1.arr.push(234);
console.log(nc1.name);//"nc1"
console.log(nc2.name);//"nc2"
console.log(nc1.arr);//[1,234]
console.log(nc2.arr);//[1]
/**
寄生组合式继承:切掉了原型对象上多余的那份父类实例属性
*/
//借用空对象作为中间媒介:空对象几乎不占内存
function extend(Child,Parent){
var F = function(){};
//改变F的原型对象的指向
F.prototype = Parent.prototype;
//子类的原型对象指向F的实例
Child.prototype = new F();
//重新指定Child的constructor指向自身
Child.prototype.constructor = Child;
//为子对象设一个uber属性,这个属性直接指向父对象的prototype属性,备用属性
Child.uber = Parent.prototype;
}
function Super(name){
//只声明基础属性和引用属性
this.name = name||'super';
this.arr = [1];
}
//声明方法
Super.prototype.say = function(){
console.log(this.name);
}
//Super.prototype....
function Sub(name){
//核心:继承父类基础属性和引用属性
Super.call(this,name);
}
extend(Sub, Super);
var sb1 = new Sub('sb1');
var sb2 = new Sub('sb2');
sb1.name = 'new sb1';
sb1.arr.push(234);
console.log(sb1.name);//"new sub1"
console.log(sb2.name);//"sub2"
console.log(sb1.arr);//[1,234]
console.log(sb2.arr);//[1]
/**
拷贝继承:如果把父对象的所有属性和方法,拷贝进子对象,
**/
function extend2(Child,Parent){
var p = Parent.prototype;
var c = Child.prototype;
for(var k in p){
c[k] = p[k]
}
c.uber = p;
}
function Animal(name){
this.name = name || 'animal';
}
Animal.prototype.say = function(){
return this.name;
}
function Cat(name,color){
Animal.call(this,name);
this.color = color;
}
extend2(Cat,Animal);
var cat = new Cat('猫','黄色');
console.log(cat.say());//"猫"
console.log(cat.name);//"猫"
console.log(cat.color);//"黄色"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment