码迷,mamicode.com
首页 > 其他好文 > 详细

构造函数继承

时间:2020-02-25 09:39:19      阅读:64      评论:0      收藏:0      [点我收藏+]

标签:eof   类的属性   parse   其他   obj   date   UNC   adp   json   

构造函数继承

属性的继承

{
    // 继承: 子类继承父类的属性和方法
    function Dad(name,age){
        this.name = name;
        this.age = age;
        this.money = "1000";
    }

    function Son(name,age){
        Dad.call(this,name,age);
        // Dad.apply(this,[name,age]);
        // Dad.bind(this)(name,age);
        /* 
            通过call、apply、bind方式
            在子类函数中执行父类函数
            修改this指向为子类函数
            这时候 父类的this也就是子类的this了,也就是 属性和方法 都拿到了!
            注:同时也要传入 响应的参数

            子类的属性和方法是可以进行添加或覆盖
        */
       this.sex = "男";
    }

    let zhangsan = new Son("张三",22);
    console.log(zhangsan);
}

原型的继承(传址问题的出现)

{
    function Dad(name,age){
        this.name = name;
        this.age = age;
        this.money = "1000";
    }
    Dad.prototype.fn = function(){
        console.log("fn");
    }
    /* 
        一般情况下:属性是放到构造函数中,方法放在原型中,那原型是否也进行继承呢?
    */
    function Son(name,age){
        Dad.call(this,name,age);
        this.sex = "男";
    }

    let zhangsan = new Son("张三",22);
    // zhangsan.fn();//报错
    {
        /*
            让子类的原型 = 父类的原型;
            问题:传址
        */
        Son.prototype = Dad.prototype;
        let zhangsan = new Son("张三",22);
        zhangsan.fn();//fn

        {
            // 在这里修改了子类的 继承的方法
            Son.prototype.fn = function(){
                console.log("重写的fn");
            }
            zhangsan.fn();//重写的fn
            // 执行父类的方法
            let zhangyi = new Dad("张一",21)
            zhangyi.fn();//重写的fn -> 是修改后的方法
        }
    }
}

传值和传址

{
    // 传值与传址
    let DadProto = {
        name:"张三",
        age:20
    }

    let SonProto = DadProto;
    SonProto.name = "李四";

    console.log(SonProto);//李四
    console.log(DadProto);//李四
    /* 
        没有修改的DadProto对象也变成了 李四
        为什么呢?
            因为简单的赋值 子对象和夫对象 有引用关系,在内存里面是同一个地址;
        这就是 传址问题:名字虽然不一样,但‘本尊‘依然是一个
        除了对象会传址外,还有啥数据类型有传址问题呢?
            所有复杂的数据类型都有传址问题;
            也就是除了简单的数据类型,其他的都是 复杂数据类型;
                number,string,undefined...
        
        简单数据类型:传值;
            它会在 内存里面新开辟一个内存 == 复制
    */
    {
        let a = 10;
        let b = a;
        b = 20;
        console.log(a,b);//10,20 -> a仍然是10
    }
}
{
    // 那如何解决复杂数据类型的相互影响呢 : 深拷贝
    let DadProto = {
        name:"张三",
        age:20,
        fn(){
            console.log("fn");
        },
        test:undefined
    }

    {
        // 简单的深拷贝方法: 序列化
        let SonProto = JSON.parse( JSON.stringify( DadProto ) );
        /* 
            JSON.stringify() 把对象转换为JSON字符串;
            JSON.parse() 把JSON字符串转换为对象;
            缺点:丢失 function、undefined 
        */
        SonProto.name = "李四";
        console.log(SonProto);//李四
        console.log(DadProto);//张三
    }

    {
        let obj = {
            name:"张三",
            age:20,
            fn(){
                console.log("fn");
            },
            test:undefined,
            arr:[1,2,3]
        }

        let obj2 = deepCopy(obj);
        obj2.name = "李四";
        console.log(obj);
        console.log(obj2);

        // 深拷贝函数 : 遍历
        /* function deepCopy(obj){
            // 给我一个对象,循环遍历对象,把值赋给 新的对象(新开辟的地址)
            let newObj = Array.isArray(obj)?[]:{};//传入的对象有可能是 数组 或者是 对象,Array.isArray() 判断是否是数组
            for(let key in obj){
                if(obj.hasOwnProperty(key)){//hasOwnProperty()判断对象属性是不是自身的属性,因为这里不需要 原型下面的属性和方法了
                    if(typeof obj[key] === "object"){//判断每一个对象是简单数据类型还是复杂数据类型 -> 是对象
                        newObj[key] = deepCopy(obj[key]);//还是对象就继续循环
                    }else{//非对象
                        newObj[key] = obj[key];//非对象就直接赋值
                    }
                }
            }
            return newObj;
        } */
        function deepCopy(obj){
            let newObj = Array.isArray(obj)?[]:{};
            for(let key in obj){
                if(obj.hasOwnProperty(key)){
                    if(typeof obj[key] === "object"){
                        newObj[key] = deepCopy(obj[key]);
                    }else{//非对象
                        newObj[key] = obj[key];
                    }
                }
            }
            return newObj;
        }
    }
}

 原型的继承

function deepCopy(obj){
    let newObj = Array.isArray(obj)?[]:{};
    for(let key in obj){
        if(obj.hasOwnProperty(key)){
            if(typeof obj[key] === "object"){
                newObj[key] = deepCopy(obj[key]);
            }else{//非对象
                newObj[key] = obj[key];
            }
        }
    }
    return newObj;
}
function Dad(name,age){
    this.name = name;
    this.age = age;
    this.money = "1000";
}
Dad.prototype.fn = function(){
    console.log("fn");
}

function Son(name,age){
    Dad.call(this,name,age);
    this.sex = "男";
}

let zhangsan = new Son("张三",22);
{
    /*
        让子类的原型 = 父类的原型;
    */
    Son.prototype = deepCopy(Dad.prototype);
    let zhangsan = new Son("张三",22);
    zhangsan.fn();//fn

    {
        // 在这里修改了子类的 继承的方法
        Son.prototype.fn = function(){
            console.log("重写的fn");
        }
        zhangsan.fn();//重写的fn
        // 执行父类的方法
        let zhangyi = new Dad("张一",21)
        zhangyi.fn();//fn -> 依然是原来的
    }
}
// 属性拷贝使用 call
// prototype使用 deepCopy()深拷贝函数 ;

组合继承

{
    // 组合继承
    function Dad(name,age){
        this.name = name;
        this.age = age;
        this.money = "1000";
    }
    Dad.prototype.fn = function(){
        console.log("fn");
    }

    function Son(name,age){
        Dad.call(this,name,age);
        this.sex = "男";
    }

    let zhangsan = new Son("张三",22);
    {
        /*
            让子类的原型 = 父类的原型;
        */
        let Link = function(){};//一个空的构造函数;
        Link.prototype = Date.prototype;
        Son.prototype = new Link();
        Son.prototype.constructor = Son;
        // 每一次实例化的时候,实例化出来的新对象会 新开辟一个地址;
        // 赋值了prototype会覆盖掉原来的constructor属性,所以需要重新指回来
        let zhangsan = new Son("张三",22);
        {
            // 在这里修改了子类的 继承的方法
            Son.prototype.fn = function(){
                console.log("重写的fn");
            }
            zhangsan.fn();//重写的fn
            // 执行父类的方法
            let zhangyi = new Dad("张一",21)
            zhangyi.fn();//fn -> 依然是原来的
        }
    }
    // 属性拷贝使用 call
    // prototype使用 组合继承;
}

 

构造函数继承

标签:eof   类的属性   parse   其他   obj   date   UNC   adp   json   

原文地址:https://www.cnblogs.com/Afanadmin/p/12359759.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!