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

原文地址:https://www.cnblogs.com/acjialiren/p/2983347.html