Effective JavaScript Item 40 避免继承标准类型
本系列作为Effective JavaScript的读书笔记。
ECMAScript标准库不大。可是提供了一些重要的类型如Array,Function和Date。在一些场合下。你或许会考虑继承当中的某个类型来实现特定的功能。可是这样的做法并不被鼓舞。
比方为了操作一个文件夹。能够让文件夹类型继承Array类型例如以下:
function Dir(path, entries) {
this.path = path;
for (var i = 0, n = entries.length; i < n; i++) {
this[i] = entries[i];
}
}
Dir.prototype = Object.create(Array.prototype);
// extends Array
var dir = new Dir("/tmp/mysite", ["index.html", "script.js", "style.css"]);
dir.length; // 0
可是能够发现。dir.length的值是0,而不是期待中的3。
发生这样的现象的原因在于:仅仅有当对象是真正的Array类型时,length属性才会起作用。
在ECMAScript标准中。定义了一个不可见的内部属性被称为
[[class]]。该属性的值仅仅是一个字符串,所以不要被误导觉得JavaScript也实现了自己的类型系统。所以,对于Array类型,这个属性的值就是“Array”。对于Function类型。这个属性的值就是“Function”。下表是ECMAScript定义的全部[[class]]
值:
那么当对象的类型确实是Array时,length属性的特别之处就在于:length的值会和该对象中被索引的属性个数保持一致。比方对于一个数组对象arr。arr[0]和arr[1]就表示该对象有两个被索引的属性。那么length的值就是2。当加入了arr[2]的时候。length的值会被自己主动同步成3。
相同地,当设置length值为2时。arr[2]会被自己主动设置成undefined。
可是当继承Array类型并创建实例时,该实例的
[[class]] 属性并非Array。而是Object。因此length属性不能正确的工作。
在JavaScript中,也提供了用于查询
[[class]] 属性的方法,即使用Object.prototype.toString方法:
var dir = new Dir("/", []);
Object.prototype.toString.call(dir); // "[object Object]"
Object.prototype.toString.call([]); // "[object Array]"
因此,更好的实现方法是使用组合而不是继承:
function Dir(path, entries) {
this.path = path;
this.entries = entries; // array property
}
Dir.prototype.forEach = function(f, thisArg) {
if (typeof thisArg === "undefined") {
thisArg = this;
}
this.entries.forEach(f, thisArg);
};
以上代码将不再使用继承。而是将一部分功能代理给内部的entries属性来实现。该属性的值是一个Array类型对象。
ECMAScript标准库中,大部分的构造函数都会依赖内部属性值如 [[class]]
来实现正确的行为。对于继承这些标准类型的子类型。无法保证它们的行为是正确的。
因此。不要继承ECMAScript标准库中的类型如:
Array。
Boolean,
Date,
Function。
Number,RegExp,String
总结
- 继承标准类型可能会导致子类的行为不对,由于标准类型会依赖于内部属性诸如 [[class]]
- 优先使用组合的方式来实现功能。而不是使用继承。
Effective JavaScript Item 40 避免继承标准类型的更多相关文章
- Effective JavaScript Item 46 优先使用数组而不是Object类型来表示有顺序的集合
本系列作为Effective JavaScript的读书笔记. ECMAScript标准并没有规定对JavaScript的Object类型中的属性的存储顺序. 可是在使用for..in循环对Objec ...
- Effective JavaScript Item 39 绝不要重用父类型中的属性名
本系列作为Effective JavaScript的读书笔记. 假设须要向Item 38中的Actor对象加入一个ID信息: function Actor(scene, x, y) { this.sc ...
- Effective JavaScript Item 51 在类数组对象上重用数组方法
Array.prototype对象上的标准方法被设计为也能够在其他对象上重用 - 即使不是继承自Array的对象. 因此,在JavaScript中存折一些类数组对象(Array-like Object ...
- Effective JavaScript Item 30 理解prototype, getPrototypeOf和__proto__的不同
本系列作为Effective JavaScript的读书笔记. prototype,getPropertyOf和__proto__是三个用来訪问prototype的方法.它们的命名方式非常类似因此非常 ...
- Effective JavaScript Item 38 调用父类的构造函数在子类的构造函数
作为这一系列Effective JavaScript的读书笔记. 在一个游戏或者图形模拟的应用中.都会有场景(Scene)这一概念.在一个场景中会包括一个对象集合,这些对象被称为角色(Actor). ...
- Effective JavaScript Item 21 使用apply方法调用函数以传入可变參数列表
本系列作为Effective JavaScript的读书笔记. 以下是一个拥有可变參数列表的方法的典型样例: average(1, 2, 3); // 2 average(1); // 1 avera ...
- Effective JavaScript Item 31 优先使用Object.getPrototypeOf,而不是__proto__
本系列作为Effective JavaScript的读书笔记. 在ES5中引入了Object.getPrototypeOf作为获取对象原型对象的标准API.可是在非常多运行环境中.也提供了一个特殊的_ ...
- Effective JavaScript Item 49 对于数组遍历,优先使用for循环,而不是for..in循环
本系列作为Effective JavaScript的读书笔记. 对于以下这段代码,能看出最后的平均数是多少吗? var scores = [98, 74, 85, 77, 93, 100, 89]; ...
- Effective JavaScript Item 37 认识this的隐式指向
本系列作为Effective JavaScript的读书笔记. CSV数据通常都会被某种分隔符进行分隔.所以在实现CSV Reader时,须要支持不同的分隔符.那么,非常自然的一种实现就是将分隔符作为 ...
随机推荐
- rescan-scsi-bus.sh linux扫盘 脚本
[root@ftp:/home/tools/shell] > yum install sg3_utils* Loaded plugins: fastestmirror Repository ba ...
- linux 系统相关命令
说明:此篇以 Debian ( ubuntu16.04 ) 命令为例 1. tab键默认是不能自动补全命令 apt install bash-completion // 安装完成之后重启系统 2. 虚 ...
- Java统计一篇文章中每个字符出现的个数
大家可以参考下面代码,有什么疑问请留言... import java.io.BufferedReader; import java.io.FileInputStream; import java.io ...
- Linux入门基础(一)
UNIX/Linux 本身是没有图形界面的,我们通常在 UNIX/Linux 发行版上看到的图形界面实际都只是运行在 Linux 系统之上的一套软件XFree86,现在则是 xorg(X.Org),而 ...
- Qt之图形(简笔画-绘制卡通蚂蚁)
简述 关于简笔画的介绍很多,有动物.水果.蔬菜.交通工具等,通常会对绘制一步步进行拆分.组合.然后绘制为我们想要的结果. 下面来介绍另外的一个种类:昆虫类-卡通蚂蚁. 简述 绘制 效果 源码 绘制 效 ...
- OCUI界面设计:滚动视图与分页控件初探
滚动视图(UIScrollView) 简单介绍 1.UIScrollView滚动视图能够排列并显示超出自身显示范围的内容. 2.UIScrollView内部整合了多种手势来达到丰富的界面展示效果. 3 ...
- POJ 1741 Tree 树的分治(点分治)
题目大意:给出一颗无根树和每条边的权值,求出树上两个点之间距离<=k的点的对数. 思路:树的点分治.利用递归和求树的重心来解决这类问题.由于满足题意的点对一共仅仅有两种: 1.在以该节点的子树中 ...
- taglist安装
注意:taglist依赖于ctags,所以要先装ctags,否则taglist装了也没法用!1.首先安装ctags1)ubuntu安装sudo apt-get install exuberant-ct ...
- BZOJ1468: Tree & BZOJ3365: [Usaco2004 Feb]Distance Statistics 路程统计
[传送门:BZOJ1468&BZOJ3365] 简要题意: 给出一棵n个点的树,和每条边的边权,求出有多少个点对的距离<=k 题解: 点分治模板题 点分治的主要步骤: 1.首先选取一个点 ...
- Git-如何将已存在的项目提交到git
1.首先在码云或者github上创建一个不带README.md的项目,然后复制远程库的地址(下面以码云为例): 2.进入本地已存在的项目目录:house touch README.md //新建说明 ...