JavaScript Patterns 6.2 Expected Outcome When Using Classical Inheritance
// 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"
- Following the Prototype Chain


- Drawbacks when Using Pattern #1
- Inherit both own properties added to this and prototype properties.
Note: reusable members should be added to the prototype.
- 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
- 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"
});

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

- 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.
- 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;
}
- 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的更多相关文章
- 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 ...
- JavaScript Patterns 6.7 Borrowing Methods
Scenario You want to use just the methods you like, without inheriting all the other methods that yo ...
- JavaScript Patterns 6.6 Mix-ins
Loop through arguments and copy every property of every object passed to the function. And the resul ...
- JavaScript Patterns 6.5 Inheritance by Copying Properties
Shallow copy pattern function extend(parent, child) { var i; child = child || {}; for (i in parent) ...
- JavaScript Patterns 6.4 Prototypal Inheritance
No classes involved; Objects inherit from other objects. Use an empty temporary constructor function ...
- JavaScript Patterns 6.3 Klass
Commonalities • There’s a convention on how to name a method, which is to be considered the construc ...
- 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 ...
- JavaScript Patterns 5.9 method() Method
Advantage Avoid re-created instance method to this inside of the constructor. method() implementatio ...
- JavaScript Patterns 5.8 Chaining Pattern
Chaining Pattern - Call methods on an object one after the other without assigning the return values ...
随机推荐
- Adb connection Error:远程主机强迫关闭了一个现有的连接
在用手机调试程序时,有时会出现“Adb connection Error:远程主机强迫关闭了一个现有的连接”的错误. 出现这种错误时,可以按照以下步骤解决: (1)运行cmd.exe,并将目录CD到\ ...
- [moka同学笔记]Yii2.0给一张表中增加一个属性
1.model中建立关联 public function getUser(){ return$this->hasOne(User::className(),['id'=>'uid']) ; ...
- 通过angularjs的directive以及service来实现的列表页加载排序分页
前两篇:(列表页的动态条件搜索,我是如何做列表页的)分别介绍了我们是如何做后端业务系统数据展示类的列表页以及动态搜索的,那么还剩下最重要的一项:数据展示.数据展示一般包含三部分: 数据列头 数据行 分 ...
- angular学习的一些小笔记(中)之双向数据绑定
<!doctype html> <html ng-app=""> <head> <script src="https://aja ...
- jQuery als.js 跑马灯
ali.js是一款滚动插件,滚动的内容可包含文字和图片.它的API也很强大,包括滚动区域可见个数.每次滚动个数.滚动方向.是否循环滚动.是否自动滚动.滚动间隔时间.滚动动画速度.动画效果.滚动方向以及 ...
- HTML5 Canvas 实现的9个 Loading 效果
Sonic.js 是一个很小的 JavaScript 类,用于创建基于 HTML5 画布的加载图像.更强大的是 Sonic.js 还提供了基于现成的例子的创建工具,可以帮助你实现更多自定义的(Load ...
- windows 80 端口占用
1. cmd 2. regidit 3. 注册表 KEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\HTTP'右边有一个'start'的DWORD ...
- javascript对象继承详解
问题 比如我们有一个"动物"对象的构造函数. function animal() { this.type = '动物'; } 还有一个"猫"对象的构造函数. f ...
- iOS Assigning to 'id<XXXDelegate>' from incompatible type 'BViewController *__strong'
在使用代理的时候, BViewController *BVC = [[BViewController alloc]init]; self.delegate = BVC; 出现这样的警告Assignin ...
- 如何在silverlight中以同步方式 获取sharepoint2013站点的当前登录账号
最近有个项目用到了silverlight要同步方式获取当前登录账号.异步的方式无法跟其他应用结合.主要先后顺序问题.但是silverlight非常不好获取到当前登录账号.即使获取到了也是异步方式获取. ...