非构造函数的继承

1. 什么是“非构造函数”的继承?

例如:

var Cat = {
    name  : '',
    color : ''
}

还有一个对象,叫做 “医生”

var cat1 = {};

cat1.name = '大毛';
cat1.color = '黄色';

var cat2 = {};

cat2.name = '二毛';
cat2.color = '黑色';

因为医生很有可能就是中国人,那么如何让医生去继承中国人呢?
也即:两个对象都是普通的对象,不是构造函数,无法使用构造函数的方式来实现继承。

2. object() 方法

Douglas Crockford 提出了一个函数,可以做到这一点,原理有点类似于构造函数继承中的,利用空对象做中介 继承

function Cat(name,color){
    return {
        name  : name,
        color : color
    }
}

这个函数的左右就是利用一个中介来将子对象的 prototype 对象指向父对象,从而通过子对象的原型链使其连到了一起。因为普通对象其prototype为未定义,所以不能直接对其赋值来实现继承。

使用:

var cat1 = Cat('大毛','黄色');
var cat2 = Cat('二毛','黑色');

3. 浅拷贝

类似于上一节的拷贝继承,只不过这里直接拷贝的是对象的属性。

function Cat(name,color){
    this.name = name;
    this.color = color;
}

使用:

var cat1 = new Cat('大毛','黄色');
var cat2 = new Cat('二毛','黑色');

但是,与原型继承类似,这里也存在假如父对象的属性等于数组或对象的话,那么实际上只是一个内存地址,不是拷贝,所以如果修改了子对象,那么父对象也会被修改,这样是不可以的。

例如:

console.log(cat1 instanceof Cat); //true
console.log(cat2 instanceof Cat); //true

看,Chinese 的东西也被改掉了,同时继承 Chinese 的所有对象的此属性,都被改掉了,而这是多么打的问题啊。
这是 jQuery 早期实现继承的方式,其只能拷贝基本类型的数据。也即是“浅拷贝”。

4. 深拷贝

其实深拷贝也来源于浅拷贝,只是对于属性值是否是基本类型进行判断,如果非基本类型的数据,继续调用即可,也就是递归的浅拷贝就行了。

function Cat(name,color){
    this.name = name;
    this.color = color;
    this.type = '猫科动物';
    this.eat = function(){console.log('吃老鼠');}
}

使用:

var cat = Cat('大毛','黄色');
console.log(cat.type); // 猫科动物
cat.eat(); // 吃老鼠。

目前,jQuery 就使用的是这种方法。

全文是在阮一峰的这三篇文章(1,2,3)的理解下写成的,也算作学习笔记吧。

没有评论

  • :arrow:
  • :grin:
  • :???:
  • :cool:
  • :cry:
  • :shock:
  • :evil:
  • :!:
  • :idea:
  • :lol:
  • :mad:
  • :mrgreen:
  • :neutral:
  • :?:
  • :razz:
  • :oops:
  • :roll:
  • :sad:
  • :smile:
  • :eek:
  • :twisted:
  • :wink: