Effective JavaScript Item 38 调用父类的构造函数在子类的构造函数
作为这一系列Effective JavaScript的读书笔记。
在一个游戏或者图形模拟的应用中。都会有场景(Scene)这一概念。在一个场景中会包括一个对象集合,这些对象被称为角色(Actor)。
而每一个角色依据其类型会有一个图像用来表示,同一时候场景也须要保存一个底层图形展示对象的引用,被称为上下文(Context):
function Scene(context, width, height, images) {
this.context = context;
this.width = width;
this.height = height;
this.images = images;
this.actors = [];
}
Scene.prototype.register = function(actor) {
this.actors.push(actor);
};
Scene.prototype.unregister = function(actor) {
var i = this.actors.indexOf(actor);
if (i >= 0) {
this.actors.splice(i, 1);
}
};
Scene.prototype.draw = function() {
this.context.clearRect(0, 0, this.width, this.height);
for (var a = this.actors, i = 0, n = a.length; i < n; i++) {
a[i].draw();
}
};
场景中全部的角色都继承自一个基类,这个基类用来抽象全部角色具有的属性和方法。比方,每一个角色对象都会保存它所在场景的引用,和坐标信息:
function Actor(scene, x, y) {
this.scene = scene;
this.x = x;
this.y = y;
scene.register(this);
}
相同地,在Actor类型的prototype对象上会定义公共的方法:
Actor.prototype.moveTo = function(x, y) {
this.x = x;
this.y = y;
this.scene.draw();
};
Actor.prototype.exit = function() {
this.scene.unregister(this);
this.scene.draw();
};
Actor.prototype.draw = function() {
var image = this.scene.images[this.type];
this.scene.context.drawImage(image, this.x, this.y);
};
Actor.prototype.width = function() {
return this.scene.images[this.type].width;
};
Actor.prototype.height = function() {
return this.scene.images[this.type].height;
};
有了角色基础类。就能够在其之上创建详细类型了。比方当创建一个宇宙飞船(SpaceShip)角色时,能够这样实现:
function SpaceShip(scene, x, y) {
Actor.call(this, scene, x, y);
this.points = 0;
}
为了让SpaceShip的实例也可以拥有全部角色应该有的属性,所以在SpaceShip的构造函数体内首先调用了父类(Actor)的构造函数,紧接着会初始化SpaceShip实例自身的属性,比方以上的points。
为了让SpaceShip类型确确实实地成为Actor类型的子类型,SpaceShip类型的prototype对象也必需要继承自Actor类型的prototype对象。这能够通过ES5提供的Object.create方法完毕(非ES5的实现方式能够參考Item
33):
SpaceShip.prototype = Object.create(Actor.prototype);
假设SpaceShip的prototype对象是通过调用Actor的构造函数来获得的,那么会出现一系列的问题:
SpaceShip.prototype = new Actor();
在调用Actor构造函数的时候,没法传入合理的參数。由于Actor接受场景对象和坐标信息作为參数,而SpaceShip类型的prototype对象的目的是为了容纳SpaceShip类型中一些公用的属性和方法。显然场景和坐标信息会随着SpaceShip实例的不同而不同。将这些信息放在prototype对象上是不合适的。
父类型的构造函数仅仅能在子类型的构造函数中被调用,而子类型的prototype对象是继承自父类型的prototype对象。
这一点在创建子类型的prototype时须要注意。
一旦完毕了子类型prototype对象的创建。就能够在其上设置公用的属性和方法了:
SpaceShip.prototype.type = "spaceShip";
SpaceShip.prototype.scorePoint = function() {
this.points++;
};
SpaceShip.prototype.left = function() {
this.moveTo(Math.max(this.x - 10, 0), this.y);
};
SpaceShip.prototype.right = function() {
var maxWidth = this.scene.width - this.width();
this.moveTo(Math.min(this.x + 10, maxWidth), this.y);
};
此时,Actor类型,SpaceShip类型以及它们的prototype对象之间的关系例如以下:
总结
- 在子类型的构造函数中调用父类型的构造函数,并显式传入this的指向。
- 使用Object.create方法创建亚型prototype对象以避免调用父类的构造函数。
Effective JavaScript Item 38 调用父类的构造函数在子类的构造函数的更多相关文章
- Effective JavaScript Item 21 使用apply方法调用函数以传入可变參数列表
本系列作为Effective JavaScript的读书笔记. 以下是一个拥有可变參数列表的方法的典型样例: average(1, 2, 3); // 2 average(1); // 1 avera ...
- Effective JavaScript Item 37 认识this的隐式指向
本系列作为Effective JavaScript的读书笔记. CSV数据通常都会被某种分隔符进行分隔.所以在实现CSV Reader时,须要支持不同的分隔符.那么,非常自然的一种实现就是将分隔符作为 ...
- Effective JavaScript Item 39 绝不要重用父类型中的属性名
本系列作为Effective JavaScript的读书笔记. 假设须要向Item 38中的Actor对象加入一个ID信息: function Actor(scene, x, y) { this.sc ...
- Effective JavaScript Item 30 理解prototype, getPrototypeOf和__proto__的不同
本系列作为Effective JavaScript的读书笔记. prototype,getPropertyOf和__proto__是三个用来訪问prototype的方法.它们的命名方式非常类似因此非常 ...
- Effective JavaScript Item 46 优先使用数组而不是Object类型来表示有顺序的集合
本系列作为Effective JavaScript的读书笔记. ECMAScript标准并没有规定对JavaScript的Object类型中的属性的存储顺序. 可是在使用for..in循环对Objec ...
- Effective JavaScript Item 10 避免使用with
本系列作为Effective JavaScript的读书笔记. Item 9:避免使用withkeyword 重点: 设计withkeyword本来是为了让代码变简洁,可是却起到了相反的效果.比方: ...
- Effective JavaScript Item 22 使用arguments来创建接受可变參数列表的函数
本系列作为Effective JavaScript的读书笔记. 在Item 21中,介绍了结合apply方法实现的可变參数列表函数average,它实际上仅仅声明了一个数组作为參数,可是利用apply ...
- Effective JavaScript Item 31 优先使用Object.getPrototypeOf,而不是__proto__
本系列作为Effective JavaScript的读书笔记. 在ES5中引入了Object.getPrototypeOf作为获取对象原型对象的标准API.可是在非常多运行环境中.也提供了一个特殊的_ ...
- Effective JavaScript Item 40 避免继承标准类型
本系列作为Effective JavaScript的读书笔记. ECMAScript标准库不大.可是提供了一些重要的类型如Array,Function和Date.在一些场合下.你或许会考虑继承当中的某 ...
随机推荐
- idea+springboot+freemarker热部署(转)
今天在学习springboot集成freemarker模板引擎修改代码时,发现每次修改一次freemarker文件时,都必须重启下应用,浏览器刷新才能显示修改后的内容,这样效率太低,每次启动一次应用都 ...
- [MobX] MobX fundamentals: deriving computed values and managing side effects with reactions
Derivations form the backbone of MobX and come in two flavors: computed values are values that can b ...
- 运行一个Hadoop Job所需要指定的属性 分类: A1_HADOOP 2015-02-02 21:33 231人阅读 评论(0) 收藏
1.设置job的基础属性 Job job = new Job(); job.setJarByClass(***.class); job.setJobName("job name") ...
- 中小研发团队架构实践之RabbitMQ快速入门及应用
原文:中小研发团队架构实践之RabbitMQ快速入门及应用 使用过分布式中间件的人都知道,程序员使用起来并不复杂,常用的客户端API就那么几个,比我们日常编写程序时用到的API要少得多.但是分布式中间 ...
- Wampserver 2.5 多网站配置方法
写在开头:本文适用于wampserver2.5版本号,和wamp的老版本号配置有语法上的差别,笔者正是由于被老版本号的配置办法给整迷糊了所以才总结了一篇针对2.5版本号的配置方法,假设您还停留在1.x ...
- [JS Compose] 2. Enforce a null check with composable code branching using Either
We define the Either type and see how it works. Then try it out to enforce a null check and branch o ...
- 【37.21%】【codeforces 721B】Passwords
time limit per test2 seconds memory limit per test256 megabytes inputstandard input outputstandard o ...
- 【心情】codeforces涨分啦!
虽然只有10分. 第二次比赛!
- PHP接口类interface使用方法
PHP同大多数的面向对象语言一样,并不支持多重继承.少数支持多重继承的语言中最著名的就是C++和Smalltalk.如果需要实现多重继承功能,在PHP中,可以通过接口,它是PHP解决多重继承问题的方法 ...
- 使用搜狐Sendcloud的Webapi发送邮件:Jodd和Apache Httpclient
最近,在使用搜狐Sendcloud发邮件. Sendcloud提供http格式的webapi,方便地发送邮件,当然是要付费的. 很早之前,http工具一直用Httpclient,后来觉得jodd ...