// the parent constructor

function Parent(name) {

    this.name = name || 'Adam';

}

// adding functionality to the prototype

Parent.prototype.say = function () {

    return this.name;

};

// empty child constructor

function Child(name) {}

inherit(Child, Parent);

A method say() added to the parent constructor’s prototype, and a call to a function called inherit() that takes care of the inheritance. The  inherit() function is not provided by the language, so you have to implement it yourself.

Classical Pattern #1—The Default Pattern

Create an object using the  Parent() constructor and assign this object to the Child()’s prototype.

function inherit(C, P) {

    C.prototype = new P();
} var kid = new Child(); kid.say(); // "Adam"
  1. Following the Prototype Chain

  1. Drawbacks when Using Pattern #1
  1. Inherit both own properties added to this and prototype properties.

Note: reusable members should be added to the prototype.

  1. It doesn't enable you to pass parameters to child constructor, which the child then passes to the parent.

Classical Pattern #2 -- Rent-a-Constructor

Passing arguments from the child to the parent.

function Child(a, c, b, d) {

    Parent.apply(this, arguments);

}

// 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
  1. The Prototype Chain

The inheritance was a one-off action that copied parent’s own properties as child’s own properties and that was about it; no __proto__ links were kept.

// 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);

}

function showMsg(msg) {

    $('#msg').append(msg).append('<br/>');

}

$(function () {

    var kid = new Child("Patrick");

    showMsg(kid.name); // "Patrick"

    showMsg(typeof kid.say); // "undefined"

});

  1. Multiple Inheritance by Borrowing constructors

Implement multiple inheritance simply by borrowing from more than one constructor

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);

  1. Pros and Cons of the Borrowing Constructor Pattern

Pros: Get true copies of the parent's own members and there's no risk that a child can accidentally overwrite a parent's property.

Cons: Nothing from the prototype gets inherited.

Classical Pattern #3—Rent and Set Prototype

function Child(a, c, b, d) {

    Parent.apply(this, arguments);

}

Child.prototype = new Parent();

The benefit is that the result objects get copies of the parent’s own members and references to the parent’s reusable functionality (implemented as members of the prototype). The child can also pass any arguments to the parent constructor. This behavior is probably the closest to what you’d expect in Java; you inherit everything there is in the parent, and at the same time it’s safe to modify own properties without the risk of modifying the parent.

A drawback is that the parent constructor is called twice, so it could be inefficient. At the end, the own properties (such as name in our case) get inherited twice.

// 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);
}
Child.prototype = new Parent(); function showMsg(msg) {
$('#msg').append(msg).append('<br/>');
}
var kid = new Child("Patrick");
kid.name; // "Patrick"
kid.say(); // "Patrick"
delete kid.name; kid.say(); // "Adam"

Classical Pattern #4—Share the Prototype

This gives you short and fast prototype chain lookups because all objects actually share the  same  prototype.

function inherit(C, P) {

    C.prototype = P.prototype;

}

Drawback

if  one  child  or  grandchild somewhere down the inheritance chain modifies the prototype, it affects all parents and grandparents.

Classical Pattern #5—A Temporary Constructor

An empty function  F(), which serves as a proxy between the child and the parent. F()’s  prototype property points to the prototype of the parent. The prototype of the child is an instance of the blank function:

function inherit(C, P) {

    var F = function () {};

    F.prototype = P.prototype;

    C.prototype = new F();

}

In this pattern, any members that the parent constructor adds to this are not inherited.

  1. Storing the Superclass

The property is called uber because “super” is a reserved word and “superclass” may

lead the unsuspecting developer down the path of thinking that JavaScript has classes.

Here’s an improved implementation of this classical pattern:

function inherit(C, P) {

    var F = function () {};

    F.prototype = P.prototype;

    C.prototype = new F();

    C.uber = P.prototype;

}
  1. Resetting the Constructor Pointer

If you don’t reset the pointer to the constructor, then all children objects will report that Parent() was their constructor, which is not useful.

// parent, child, inheritance

function Parent() {}

function Child() {}

inherit(Child, Parent);

// testing the waters

var kid = new Child();

kid.constructor.name; // "Parent"

kid.constructor === Parent; // true

function inherit(C, P) {

    var F = function () {};

    F.prototype = P.prototype;

    C.prototype = new F();

    C.uber = P.prototype;

    C.prototype.constructor = C;

}

Create temporary (proxy) constructor once and only change its prototype. You can use an immediate function and store the proxy function in its closure:

var inherit = (function () {

        // This will only be executed once which means only one function object is created for every inheritance.

        var F = function () {};     

        return function (C, P) {

        F.prototype = P.prototype; // F.prototype.constructor is pointed to Parent.

        C.prototype = new F();

        C.uber = P.prototype;

        C.prototype.constructor = C;

       }

}());

References: 

JavaScript Patterns - by Stoyan Stefanov (O`Reilly)

JavaScript Patterns 6.2 Expected Outcome When Using Classical Inheritance的更多相关文章

  1. JavaScript Patterns 7.1 Singleton

    7.1 Singleton The idea of the singleton pattern is to have only one instance of a specific class. Th ...

  2. JavaScript Patterns 6.7 Borrowing Methods

    Scenario You want to use just the methods you like, without inheriting all the other methods that yo ...

  3. JavaScript Patterns 6.6 Mix-ins

    Loop through arguments and copy every property of every object passed to the function. And the resul ...

  4. JavaScript Patterns 6.5 Inheritance by Copying Properties

    Shallow copy pattern function extend(parent, child) { var i; child = child || {}; for (i in parent) ...

  5. JavaScript Patterns 6.4 Prototypal Inheritance

    No classes involved; Objects inherit from other objects. Use an empty temporary constructor function ...

  6. JavaScript Patterns 6.3 Klass

    Commonalities • There’s a convention on how to name a method, which is to be considered the construc ...

  7. JavaScript Patterns 6.1 Classical Versus Modern Inheritance Patterns

    In Java you could do something like: Person adam = new Person(); In JavaScript you would do: var ada ...

  8. JavaScript Patterns 5.9 method() Method

    Advantage Avoid re-created instance method to this inside of the constructor. method() implementatio ...

  9. JavaScript Patterns 5.8 Chaining Pattern

    Chaining Pattern - Call methods on an object one after the other without assigning the return values ...

随机推荐

  1. matlab 调用dos命令和文件操作

    第一.利用!直接调用,简单方便,可以带操作对象:!del A.bat 第二.调用system函数或者dos函数,既可以实现功能,又返回参数,能检查执行情况,方便后面程序的开发,推荐这个 [status ...

  2. Android中GPS定位的简单应用

    在Android中通过GPS获得当前位置,首先要获得一个LocationManager实例,通过该实例的getLastKnownLocation()方法获得第一个的位置,该方法的说明如下: void ...

  3. Vue从零开始(一)

    一.什么是Vue? Vue.js(读音 /vjuː/, 类似于 view) 是一套构建用户界面的 渐进式框架.与其他重量级框架不同的是,Vue 采用自底向上增量开发的设计.Vue 的核心库只关注视图层 ...

  4. HubSpot – 网站开发必备的 jQuery 信息提示库

    HubSpot 一款功能丰富的 jQuery 消息提示插件.它可以帮助你个性化显示您的应用程序的事务性消息.您可以轻松地包裹 Ajax 请求进度,成功和错误消息,还可以添加操作链接到您的消息中. Hu ...

  5. Salvattore:CSS 驱动的 jQuery Masonry 插件

    Salvattore 是一个 jQuery 砌体的替代,使用 CSS 驱动的配置.Salvattore 根据您指定的列数组织你的 HTML 元素.容器中的每一个项目会一个接一个被放置在列内,只需要简单 ...

  6. Ouibounce – 在用户离开你网站时显示模态弹窗

    Ouibounce 是一个微小的库,用于实现在用户离开你的网站的时候显示一个模式窗口.这个库可以帮助你增加着陆页的转换率. Ouibounce 会在当鼠标光标移动到接近(或通过)视口(viewport ...

  7. Voix.js – 使用声音来控制和操纵你的网站

    我们通常使用鼠标和键盘(在移动端使用触摸)来操作网站,如今 Voix.js 能够让我们使用声音控制网站,很酷吧?它可以启动和停止侦听麦克风,在检测到一个给定的关键字时触发绑定的特定事件.Voix.js ...

  8. 高端大气上档次!10个精美的国外HTML5网站欣赏

    这篇文章挑选了10个高端大气上档次的 HTML5 网站分享给大家.作为下一代网页语言,HTML5 加入中众多的语义化标签,例如 video.audio.section.article.header.f ...

  9. jQuery立体式数字滚动条增加

    1.html结构 <div class="numberRun1"></div> 2.js <script type="text/javasc ...

  10. 轻松掌握:JavaScript装饰者模式

    装饰者模式 在传统的面向对象语言中,给对象添加功能常常使用继承的方式,但继承的方式会带来问题:当父类改变时,他的所有子类都将随之改变. 当JavaScript脚本运行时,在一个对象中(或他的原型上)增 ...