Effective JavaScript Item 36 实例状态仅仅保存在实例对象上
本系列作为EffectiveJavaScript的读书笔记。
一个类型的prototype和该类型的实例之间是”一对多“的关系。那么,须要确保实例相关的数据不会被错误地保存在prototype之上。
比方,对于一个实现了树结构的类型而言,将它的子节点保存在该类型的prototype上就是不对的:
function Tree(x) {
this.value = x;
}
Tree.prototype = {
children: [], // should be instance state!
addChild: function(x) {
this.children.push(x);
}
};
var left = new Tree(2);
left.addChild(1);
left.addChild(3);
var right = new Tree(6);
right.addChild(5);
right.addChild(7);
var top = new Tree(4);
top.addChild(left);
top.addChild(right);
top.children; // [1, 3, 5, 7, left, right]
当状态被保存到了prototype上时。全部实例的状态都会被集中地保存,在上面这样的场景中显然是不对的:本来属于每一个实例的状态被错误地共享了。例如以下图所看到的:
正确的实现应该是这种:
function Tree(x) {
this.value = x;
this.children = []; // instance state
}
Tree.prototype = {
addChild: function(x) {
this.children.push(x);
}
};
此时,实例状态的存储例如以下所看到的:
可见。当本属于实例的状态被共享到prototype上时,或许会产生问题。在须要在prototype上保存状态属性前。一定要确保该属性是可以被共享的。
整体而言,当一个属性是不可变(无状态)的属性时,就能将它保存在prototype对象上(比方方法可以被保存在prototype对象上就是由于这一点)。当然,有状态的属性也可以被放在prototype对象上,这要取决于详细的应用场景,典型的比方用来记录一个类型实例数量的变量。
使用Java语言作为类比的话,这类可以存储在prototype对象上的变量就是Java中的类变量(使用statickeyword修饰)。
总结:
- 当在prototype对象上存放可变数据时,可能会带来问题。
- 普通情况下,每一个实例特有的可变属性须要被存放在实例本身上。
Effective JavaScript Item 36 实例状态仅仅保存在实例对象上的更多相关文章
- Effective JavaScript Item 35 使用闭包来保存私有数据
本系列作为EffectiveJavaScript的读书笔记. JavaScript的对象系统从其语法上而言并不鼓舞使用信息隐藏(Information Hiding).由于当使用诸如this.name ...
- [Effective JavaScript 笔记]第51条:在类数组对象上复用通用的数组方法
前面有几条都讲过关于Array.prototype的标准方法.这些标准方法被设计成其他对象可复用的方法,即使这些对象并没有继承Array. arguments对象 在22条中提到的函数argument ...
- Android笔记之自定义的RadioGroup、RadioButton,以及View实例状态的保存与恢复
效果图 activity_main.xml <?xml version="1.0" encoding="utf-8"?> <LinearLay ...
- Effective JavaScript Item 34 在prototype上保存方法
本系列作为EffectiveJavaScript的读书笔记. 不使用prototype进行JavaScript的编码是全然可行的,比如: function User(name, passwordHas ...
- Effective JavaScript Item 38 调用父类的构造函数在子类的构造函数
作为这一系列Effective JavaScript的读书笔记. 在一个游戏或者图形模拟的应用中.都会有场景(Scene)这一概念.在一个场景中会包括一个对象集合,这些对象被称为角色(Actor). ...
- Effective JavaScript Item 37 认识this的隐式指向
本系列作为Effective JavaScript的读书笔记. CSV数据通常都会被某种分隔符进行分隔.所以在实现CSV Reader时,须要支持不同的分隔符.那么,非常自然的一种实现就是将分隔符作为 ...
- Effective JavaScript Item 21 使用apply方法调用函数以传入可变參数列表
本系列作为Effective JavaScript的读书笔记. 以下是一个拥有可变參数列表的方法的典型样例: average(1, 2, 3); // 2 average(1); // 1 avera ...
- Effective JavaScript Item 46 优先使用数组而不是Object类型来表示有顺序的集合
本系列作为Effective JavaScript的读书笔记. ECMAScript标准并没有规定对JavaScript的Object类型中的属性的存储顺序. 可是在使用for..in循环对Objec ...
- Effective JavaScript Item 51 在类数组对象上重用数组方法
Array.prototype对象上的标准方法被设计为也能够在其他对象上重用 - 即使不是继承自Array的对象. 因此,在JavaScript中存折一些类数组对象(Array-like Object ...
随机推荐
- jquery.lazyload.js图片延迟加载(懒加载)--转载
一.插件介绍 jquery.lazyload.js 是一个用 JavaScript 编写的jQuery 插件. 它可以延迟加载长页面中的图片. 在浏览器可视区域外的图片不会被载入, 直到用户将页面滚动 ...
- setTimeout()与setInterval() 问题
提示:setTimeout() 只执行 code 一次.如果要多次调用,请使用 setInterval() 或者让 code 自身再次调用 setTimeout(). 1. setInterval(c ...
- java 数字前自动补零实现
/** * 里数字转字符串前面自动补0的实现. * */ public class TestStringFormat { public static void main(String[] args) ...
- AOJ 2249 Road Construction(Dijkstra+优先队列)
[题目大意] http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=2249 [题目大意] 一张无向图,建造每条道路需要的费用已经给出, 现 ...
- iOS多线程总结(二)NSOperation
NSOperation.h定义了NSOperation,内容非常的简洁,NSOperation本身是一个抽象类,定义了一个要执行的Task,NSOperationQueue是一个Task队列,当Tas ...
- Spring、Spring自动扫描和管理Bean
Spring2.5为我们引入了组件自动扫描机制,它可以在类路径下寻找标记了@Component.@Service.@Controller.@Repository注解的类,并把这些类纳入到spring容 ...
- MySQL- InnoDB锁机制
InnoDB与MyISAM的最大不同有两点:一是支持事务(TRANSACTION):二是采用了行级锁.行级锁与表级锁本来就有许多不同之处,另外,事务的引入也带来了一些新问题.下面我们先介绍一点背景知识 ...
- php技能考试每日一练
PHP技術者認定 1, [日本語文字のメール送信] (2016年10月31日)以下のコードは桃家タローさん宛てにメールを送るためのものである.コード内の[(1)]に入る正しいものを1つ次の記述の中から ...
- 测试中的代码分享~将可以合并的方法去合并Func不赖
在面向对象的设计中,我们经常会谈到“重构”,而重构之中有个叫合并方法的,就是将多个方法干的事类似,或者说,方法体的长向很像,那么,我们需要去考虑,将它们进行抽象! 原来的代码: /// <sum ...
- 【Stackoverflow好问题】Java += 操作符实质
问题 直到今天,我都一直以为: i += j 等同于 i = i + j; 但如果有: int i = 5; long j = 8; 这时 i = i + j不能编译.但i += j却能够编译.这说明 ...