// 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. Windows Server 2012 配置多用户远程桌面

    前段时间因为需要多用户同时远程连接 windows server 2012,但找了半天也没找到远程桌面管理,最后从搜索中找到如下方法,经测试可行! 打开注册表,进入路径: [HKEY_LOCAL_MA ...

  2. FNV哈希算法

    由来:FNV哈希算法全名为Fowler-Noll-Vo算法,是以三位发明人Glenn Fowler,Landon Curt Noll,Phong Vo的名字来命名的,最早在1991年提出. 特点和用途 ...

  3. First day on cnblogs,破壳日~~

    突然很想找个地方写一点文章,又想到了这个老账号:没有因长期静默被删号实在是很感动...好吧,就这样纪念一下.第一天. I suddenly wanna write something and reca ...

  4. Framer – 将视觉搞转换为更真实的动态原型

    Framer 是一个 JavaScript 框架,简化了创建现实原型,实现完整的3D效果.以一种简单,可读的和强大的方式定义交互和创建动画. 另外还有 Framer Generator  是一个桌面应 ...

  5. Grid – 入门必备!简单易懂的响应式设计指南

    如今,人们使用各种各样的移动设备访问网页,设计师们需要去适配不同的屏幕,让用户在都能有最佳的浏览体验.Grid 是一个简单的响应式设计指南,按照这些简单的步骤,你的就能够掌握基础的响应网页设计技巧. ...

  6. Pexels Videos – 可以免费商业使用的短视频

    Pexels 是一个巨大的平台,提供免费的精美照片,很多设计师和博客每天用它来寻找他们的个人和商业项目的照片.现在我们想介绍 Pexels 视频,他是用来帮助你找到免费的视频.所有的 Pexels 视 ...

  7. .NET正则表达式匹配Silverlight

    这是一个.NET正则表达式匹配工具的Silverlight 在页面中加入以下代码就可以了: <"> <param name="source" value ...

  8. ThinkPHP3.2 G函数代码及 使用方法

    ThinkPHP3.2 G函数代码及 使用方法 代码: // 内存是否可调用 define('MEMORY_LIMIT_ON',function_exists('memory_get_usage')) ...

  9. 汉王云名片识别(SM)组件开发详解

    大家好,最近在DeviceOne平台上做了一个汉王云名片识别的功能组件.下面把我开发过程给大家做一个分享,希望可以帮助到大家. 下面我把我的思路给大家讲解一下.   1.找到我要集成的sdk,也就是汉 ...

  10. 【问题及解决】fonts/fontawesome-webfont.woff2 404 (Not Found)

    问题: 虽然网页正常显示和运行,但是有2个字体文件出现404错误.像笔者这种强迫症是接受不了的. 解决: 因为笔者的服务器是虚拟主机,只需要在主机控制器平台添加对应的MIME类型即可. 这样服务器就支 ...