• javascript中的继承[三] 基于对象(《ObjectOriented JavaScript》第六章)


    构造函数能生成实例,又有prototype属性,就成了继承的好帮手。

    不用构造函数,js生成对象还有一种更方便的方式,字面量。第一章中的例子;

    /*字面量*/
    var jim = {};
    jim.name = "Jim";
    jim.sayHello = function(){alert(this.name);};
    
    var hanmeimei = {
        name:"hanmeimei",
        sayHello:function(){alert(this.name);}
    };

    不构造函数,我们如何继承?

    (一)浅复制

    我们可以继承父母的基因,也可以像兄弟姐妹朋友们学习喽,任何人都可以。我们完全可以直接继承一个对象,通过下面的方法:

    function extendCopy(p, c){
        var c = c || {};
        for(var i in p){
            c[i]=p[i];
        } 
        return c; 
    }

    这段代码也非常实用,早起的jQuery,Prototype都有这种实现

    var jim = {};
    jim.name = "Jim";
    jim.sayHello = function(){alert(this.name);};
    
    /*
    var hanmeimei = {
        name:"hanmeimei",
        sayHello:function(){alert(this.name);}
    };
    */
    
    var hanmeimei = extendCopy(jim);
    hanmeimei.name = "hanmeimei";
    hanmeimei.sayHello();

    (二)深复制

    上面的复制函数有个潜在的问题

    如果被继承的对象有一个属性 是数组对象/等引用变量,而不是值变量,继承对象中的这个属性,也指向那个变量的,他们共享了数组、方法,这往往不是我们希望的。

    如:

    var a = {
        numbers:[1,2,3],
        letters:['a','b'],
        obj:{prop:1},
        x:1
    };
    
    var b = extentdCopy(a);

    这种情形下,对象a 和 b的numbers/letters/obj 属性是共享的,如果我们修改b.numbers,  a.numbers也就变了,这不是我们想要的

    我们不能通过简单的 b.numbers = a.numbers 实现根本的复制。

    怎么办呢?可以空过递归实现,看以下代码:

    function deepCopy(p, c){
        var  c = c || {};
        for(var i in p){
            if(type of p[i] === 'object'){
                c[i] = (p[i].constructor === Array) ? [] : {};
                deepCopy(p[i], c[i]);
            } else {
                c[i] = p[i];
            }
        }
    }

    这样,继承元素 和 被继承元素 就不会有共享的属性了,只有方法是共享的,属性都是重建的,这样就解决了上面 a 和 b 继承的问题

    (三)object(o)

    我们还有一种快捷的方式,生成一个共享方法的新对象:就是把父“对象”当做prototype,通过临时构造函数生成一个新对象。

    对象虽然是在函数内部用构造函数生成的,但是从外部看,我们的确是用一个对象产生了一个新的对象:

    function object(o){
        function F(){};
        F.prototype  = o;
        return new F();
    }

    似成相识吧

    var jim = {};
    jim.name = "Jim";
    jim.sayHello = function(){alert(this.name);};
    
    /*
    var hanmeimei = {
        name:"hanmeimei",
        sayHello:function(){alert(this.name);}
    };
    
    
    var hanmeimei = extendCopy(jim);
    hanmeimei.name = "hanmeimei";
    hanmeimei.sayHello();
    
    */
    var hanmeimei = object(jim);
    hanmeimei.name = "hanmeimei";
    hanmeimei.sayHello();

    优缺点不再赘述,和上一章节一样:链式的继承 扁平的继承 各有千秋

    (四)一、三方式的混杂模式,通过(三)继承对象,通过(一)扩展对象

    function objectPlus(o, stuff){
       var n = object(o);
       extendCopy(n,stuff);
       return n;
    }

    通过(一)(二)(三) 可以衍生出很多对象继承的方法:

    多重继承:

    function multi(){
        var n = {}, stuff, j = 0, len = arguments.length;
        for (j = 0; j < len; j++){
            stuff = arguments[j];
            extendCopy(n,stuff);
        }
        return n;
    }

    这种方式实现的多重继承缺点很明显。其实前后两篇文章中介绍的方式都各有缺点,结合自己的需要改善即可。

    聪明的你,读到这里,也许已经弄清继承的基本思路。后面一篇文章来个大汇总。




    苦逼码农一个,
    人力资源管理专业本科毕业,
    懂点c#,
    懂点javascript,
    懂点sql,
    懂点设计模式
    ...

    @我是赵六六

    q:329952402

  • 相关阅读:
    开放式最短路径优先OSPF
    第一课:docker基本知识
    docker 基础
    mycat
    nginx
    keepalived
    mariadb 读写分离
    ansible
    转载 树莓派vnc 教程
    基础命令2
  • 原文地址:https://www.cnblogs.com/acjialiren/p/2983347.html
Copyright © 2020-2023  润新知