JavaScript学习笔记(三十二) 经典继承模式二-借用构造方法

经典模式二-借用构造方法(Classical Pattern #2—Rent-a-Constructor)

接下来这个模式解决了从子(child)构造函数向父(parent)构造函数传递参数的问题。它借用parent构造函数,传递被绑定给this的child对象和所有参数:
function Child(a, c, b, d) {
    Parent.apply(this, arguments);
}
通过这种你方法只可以继承在parent构造函数中添加给this的属性,你不会继承任何添加给原型的成员(members)。

使用借用构造函数模式,子对象将获得继承成员的拷贝,不像经典模式一获得的仅仅是引用。下面这个例子将会展示不同之处:
// a parent constructor
function Article() {
    this.tags = ['js', 'css'];
}
var article = new Article();
// a blog post inherits from an article object
// via the classical pattern #1
function BlogPost() {}
BlogPost.prototype = article;
var blog = new BlogPost();
// note that above you didn't need `new Article()`
// because you already had an instance available
// a static page inherits from article
// via the rented constructor pattern
function StaticPage() {
    Article.call(this);
}
var page = new StaticPage();
alert(article.hasOwnProperty('tags')); // true
alert(blog.hasOwnProperty('tags')); // false
alert(page.hasOwnProperty('tags')); // true
在这段代码快中,parent构造函数Article()被用两种方法继承。默认模式中让blog对象能够通过原型链访问tag属性,因此,它没有tag作为一个自身属性并且hasOwnProperty()返回falsepage对象有一个自身tag属性因为使用借用构造函数模式创建的新对象会得到一份parent的tags属性的拷贝(而不是引用)。

注意修改继承的tag属性的不同之处:
blog.tags.push('html');
page.tags.push('php');
alert(article.tags.join(', ')); // "js, css, html"
在这个例子中,子对象blog修改了tag属性,并且这种方法也修改了parent,因为本质上来说blog.tagsarticle.tags指向的是同一个数组。改变page.tags不会影响parent的article,因为page.tags是一份在继承期间单独创建的拷贝。

原型链(The Prototype Chain)

让我们看一下使用这种模式和熟悉的Parent()和Child构造函数原型链是怎样的,在这种新模式中 Child()将会有一点修改:
// the parent constructor
function Parent(name) {
    this.name = name || 'Adam';
}
// adding functionality to the prototype
Parent.prototype.say = function () {
    return this.name;
};
// child constructor
function Child(name) {
    Parent.apply(this, arguments);
}
var kid = new Child("Patrick");
kid.name; // "Patrick"
typeof kid.say; // "undefined"

如果你看一下图6-4,你就会发现在new Child()对象和Parent之间没了连接(link)。这是因为Child.prototype根本就没被使用并且简单的指向一个空对象(blank object)。
使用这种模式,kid获得了它的自身属性name,但是say方法从未被继承,并且试图调用它将会导致一个错误。这种继承有个一次性(one-off)的的动作,就是复制parent的自身属性作为child的自身属性,仅此而已;没有__proto__连接被保持。
图6-4:


通过借用构造函数实现多继承(Multiple Inheritance by Borrowing Constructors)

使用借用构造函数模式,实现多继承是可能的,简单地通过借用多个构造函数。
function Cat() {
    this.legs = 4;
    this.say = function () {
        return "meaowww";
    }
}
function Bird() {
    this.wings = 2;
    this.fly = true;
}
function CatWings() {
    Cat.apply(this);
    Bird.apply(this);
}
var jane = new CatWings();
console.dir(jane);
运行结果如下,任何重复的属性会被处理,只有最后一个会被保留。
JavaScript学习笔记(三十二) 经典继承模式二-借用构造方法_第1张图片

借用构造函数模式的优点和缺点(Pros and Cons of the Borrowing Constructor Pattern)

这种模式的一个很明显的缺点就是原型上的属性都不会被继承,就像前面提到的那样,原型是添加复用的方法和属性的地方,这些属性和方法不会为每个实例都创建一次。
一个好处就是你可以得到一份parent自身属性的拷贝,没有child能够意外覆盖parent的属性的风险。

那么如何让Child也能继承原型属性呢?在前面这种情况,kid如何才能够方法say()方法呢?下一种模式将会解决这些问题。


你可能感兴趣的:(JavaScript学习笔记(三十二) 经典继承模式二-借用构造方法)