JS继承的实现方式

原型链继承:
//原型链继承:把父类的私有+公有的属性和方法,都作为子类公有的属性;
    //核心:不是把父类私有+公有的属性克隆一份一模一样的给子类的公有吧;他是通过__proto__建立和子类之间的原型链,当子类的实例需要使用父类的属性和方法的时候,可以通过__proto__一级级找上去使用;
    function F(){//父类;
        this.x=100;
        this.y=300;
    }
    F.prototype.showX=function(){
        alert(123);
    };
    function S(){//子类;
        this.y=200;
    }
    S.prototype=new F;//子类公有方法上继承父类私有+公有的属性
    S.prototype.constructor=S;//添加子类constructor指向
    var p1=new S;
    var p2=new S;
    console.dir(p1)
    /*
    * 私有属性:y:200
    * __proto__:
    *   constructor:S;
    *   x:100;
    * __proto__:
    *   constructor:F;
    *   showX:function(){}
    *
    *
    * */
    //p1.__proto__.__proto__.showX();//跳过了私有属性的查找,直接到公有属性上去找
    //p1.showX();//会根据原型链一级级的往上查找;
    //S.prototype.__proto__.showX()
    //F.prototype.showX();
    //alert(p1.y)
    p1.__proto__.__proto__.showX=function(){
        alert('456789')
    }
    p1.showX();
    p2.showX();

call继承:

//call继承:把父类私有的属性和方法继承给了子类私有的属性和方法;
    function F(){
        this.x=100;
        this.y=200;
    }
    var f1=new F;
    console.dir(f1)
    function S(){
        F.call(this)
        this.z=300;
    }
    var p1=new S;
    console.dir(p1)
    //私有属性:x:100; y:200
冒充继承:
//冒充继承:把父类私有+公有的属性和方法,克隆(for in循环)了一份一模一样的给子类私有的属性和方法;
    function F(){//父类; 父类私有的属性和方法
        this.x=100;
        this.y=300;
    }
    F.prototype.showX=function(){//父类共有的属性和方法;
        alert(123);
    };
    function S(){
        var tmp=new F;
        console.dir(tmp)
        for(var attr in tmp){
            this[attr]=tmp[attr];
        }
    };
    var p1=new S;
    console.dir(p1)
混合继承:call继承+原型链继承
/*
    * call继承:把父类私有的属性和方法,都给了子类私有的属性和方法---call;
    * 原型链继承:把父类私有+公有的属性和方法,都给了子类公有的属性和方法
    * 问题:父类私有的给了子类私有,也给了子类公有
    * */
    function F(){
        this.x=100;
    }
    F.prototype.showX=function(){};
    function S(){
        F.call(this);//完成了call继承
    };
    S.prototype=new F;//完成了原型链继承;
    var p1=new S;
    console.dir(p1);
    /*
    * 私有属性:x:100;
    * __proto__:
    *   x:100;
    * __proto__:
    *   constructor:F,
    *   showX:function...
    * */
 
混合继承:call继承+拷贝继承
//混合继承:call继承+拷贝继承
function extend(newEle,oldEle){
    for(var attr in oldEle){
        newEle[attr]=oldEle[attr];
    }
}
function F(){
    this.x=100;
    this.showX=function(){}
}
F.prototype.getX=function(){};
F.prototype.getX1=function(){};
var f1=new F;
console.dir(f1)
function S(){
    F.call(this)//call继承
}
extend(S.prototype, F.prototype);//拷贝继承
S.prototype.cc=function(){ }
var p1=new S;
console.dir(p1);
寄生式组合: call继承+Object.create();
//寄生式组合: call继承+Object.create();
function F(){
    this.x=100;
}
F.prototype.showX=function(){};
function S(){
    F.call(this)//只继承了私有的;
}

function Tmp(){};
Tmp.prototype= F.prototype;//只把父级公有的属性和方法过渡到了一个空类的原型上;
S.prototype=new Tmp;
S.prototype.constructor=S;

var p1=new S;
console.dir(p1)

for in拷贝

var obj={name:'zhufeng',age:8};
var obj2={}
function extend(newEle,oldEle){
    for(var attr in obj){
        obj2[attr]=obj[attr];
    }
}
//for in循环在遍历时,默认会把自己的私有和它所属原型上扩展的属性和方法都遍历到
//obj.propertyIsEnumerable() 、 obj.hasOwnProperty()判断是否私有属性
Object.prototype.aaa=function(){}
var obj={
    name:'小明',
    age:8
}
console.log(obj)//obj.__proto__ 上有aaa(){}
for(var key in obj){
    // if(obj.propertyIsEnumerable(key)){
    if(obj.hasOwnProperty(key)){
        console.log(key) //name age
    }
}

 其它:

关于Object.create()

Object.prototype.aaa=function(){}
var obj={
    name:'小明',
    age:8
}
var obj2=Object.create(obj) //创建一个新对象,把新对象obj作为这个对象的原型
console.log(obj2)


//封装Object.create()
function object(o){
    function Fn(){}
    Fn.prototype=o
    return new Fn;
}
var newObj=object(obj)

原文地址:https://www.cnblogs.com/sayidf/p/9250629.html