[Effective JavaScript 笔记]第51条:在类数组对象上复用通用的数组方法
前面有几条都讲过关于Array.prototype的标准方法。这些标准方法被设计成其他对象可复用的方法,即使这些对象并没有继承Array。
arguments对象
在22条中提到的函数arguments对象。它是一个类数组对象,并不是一个标准的数组,所以无法使用数组原型中的方法,因此无法使用arguments.forEach这样的形式来遍历每一个参数。这里我们必须使用call方法来对使用forEach方法。
function highlight(){
[].forEach.call(arguments,function(widget){
widget.setBackground('yellow');
});
}
forEach是一个函数对象,所以它继承了Function.prototype对象中的call方法。这里就可以使用一个指定的对象作为函数内部this的绑定对象来调用它,并紧随任意数量的参数。
## NodeList对象
在Web平台,DOM的NodeList类是另一个类数组对象。类似的document.getElementsByTagName会返回一个NodeList类数组对象。这个对象也没有继承自Array.prototype.
类数组对象
怎样构建一个类数组对象?
具有一个范围在0到2^32-1的整形length属性
length属性大于该对象的最大索引。索引是一个范围在0到2^32-1的整数,它的字符串表示是该对象中的一个key
实现上面这两点,就可以使一个对象与Array.prototype中任一方法兼容。
一个简单的对象字面量也可以用来创建一个类数组对象。
var arrayLike={0:'a',1:'b',2:'c',length:3};
var res=Array.prototype.map.call(arrayLike,function(s){
return s.toUpperCase();
});
res;//['A','B','C']
字符串
也是可以表现为数组,因为它们是可索引,并且其长度也可以通过length属性获取。
因此,Array.protoype中的方法操作字符串时并不会修改原始字符串。
var res=Array.prototype.map.call('abc',function(s){return s.toUpperCase();});
res;//['A','B','C']
模拟数组
模拟数组的所有行为,归功于数组行为的两方面:
将length属性值设为小于n的值会自动地删除索引值大于或等于n的所有属性
增加一个索引值为n(大于或等于length属性值)的属性会自动地设置length属性为n+1
其中第2条规则不好实现,因为需要监控索引属性的增加以自动地更新length属性。
对于Array.prototype中的方法,这两条都不是必须的,因为在增加或删除索引属性的时候它们都会强制地更新length属性。
Array方法中只有一个不是通用的,即数组连接方法concat。该方法可以由任意的类数组接收者调用,但它会检查其参数[[Class]]属性。如果参数是一个真实的数组,那么concat会将该数组的内容连接起来作为结果;否则,参数将以一个单一的元素来连接。
例如,不能简单地连接一个以arguments对象作为内容的数组。
function namesColumn(){
return ['Names'].concat(arguments);
}
namesColumn('张三','李四','王五');//["Names", Arguments[3]0: "张三"1: "李四"2: "王五"callee: namesColumn()length: 3Symbol(Symbol.iterator): values()__proto__: Object]
使concat方法将一个类数组对象视为真实数组,需要把类数组转换为真正的数组。使用slice对类数组对象进行转换。
function namesColumn(){
return ['Names'].concat([].slice.call(arguments));
}
namesColumn('张三','李四','王五');//["Names", "张三", "李四", "王五"]
提示
对于类数组对象,通过提取方法对象并使用其call方法来复用通用的Array方法
任意一个具有索引属性和恰当length属性的对象都可以使用通用的Array方法
[Effective JavaScript 笔记]第51条:在类数组对象上复用通用的数组方法的更多相关文章
- [Effective JavaScript 笔记]第28条:不要信赖函数对象的toString方法
js函数有一个非凡的特性,即将其源代码重现为字符串的能力. (function(x){ return x+1 }).toString();//"function (x){ return x+ ...
- [Effective JavaScript 笔记] 第4条:原始类型优于封闭对象
js有5种原始值类型:布尔值.数字.字符串.null和undefined. 用typeof检测一下: typeof true; //"boolean" typeof 2; //&q ...
- [Effective JavaScript 笔记] 第5条:避免对混合类型使用==运算符
“1.0e0”=={valueOf:function(){return true;}} 是值是多少? 这两个完全不同的值使用==运算符是相等的.为什么呢?请看<[Effective JavaSc ...
- [Effective JavaScript 笔记]第27条:使用闭包而不是字符串来封装代码
函数是一种将代码作为数据结构存储的便利方式,代码之后可以被执行.这使得富有表现力的高阶函数抽象如map和forEach成为可能.它也是js异步I/O方法的核心.与此同时,也可以将代码表示为字符串的形式 ...
- [Effective JavaScript 笔记]第40条:避免继承标准类
ECMAScript标准库里配备了许多重要的类,如Array,function,以及Date等.扩展这些类生成子类可以方便完成很多工作,但它们的定义具有很多特殊的行为,所以很难写出行为正确的类. Ar ...
- [Effective JavaScript 笔记]第58条:区分数组对象和类数组对象
示例 设想有两个不同类的API.第一个是位向量:有序的位集合 var bits=new BitVector(); bits.enable(4); bits.enable([1,3,8,17]); bi ...
- [Effective JavaScript 笔记]第68条:使用promise模式清洁异步逻辑
构建异步API的一种流行的替代方式是使用promise(有时也被称为deferred或future)模式.已经在本章讨论过的异步API使用回调函数作为参数. downloadAsync('file.t ...
- [Effective JavaScript 笔记]第66条:使用计数器来执行并行操作
第63条建议使用工具函数downloadAllAsync接收一个URL数组并下载所有文件,结果返回一个存储了文件内容的数组,每个URL对应一个字符串.downloadAllAsync并不只有清理嵌套回 ...
- [Effective JavaScript 笔记]第22条:使用arguments创建可变参数的函数
第21条讲述使用可变参数的函数average.该函数可处理任意数量的参数并返回这些参数的平均值. 如何创建可变参数的函数 1.实现固定元数的函数 书上的版本 function averageOfArr ...
随机推荐
- 系统安全扫描工具(appscan)的扫描类型小记
扫描分类 不同场景需要使用不同方式的扫描类型.不能盲目的.暴力的去折腾. 自动扫描 刚开始扫描的时候适合用这种方式.有助于,理解整个网站的结构. 需要注意的是:去伪静态和业务冗余 伪静态 url结构相 ...
- Entity Framework若干个扩展
声明 这里有此东西是参考各大神修改和补充而来,有些地方就找不到原文章的地址了,一参考地址如下: http://www.cnblogs.com/ahui/archive/2011/08/04/21272 ...
- mac版beyond compare 4 中对比class文件
http://www.scootersoftware.com/download.php?zz=moreformats 这个网址中没有mac版本的class文件对比的file format.只能自己造了 ...
- [BZOJ2038]小Z的袜子(莫队算法)
题目:http://www.lydsy.com/JudgeOnline/problem.php?id=2038 分析:莫队算法 莫队算法是一种思想…… 处理问题:不带修改的区间询问 使用要求:[l-1 ...
- GridView的常规用法
GridView控件在Asp.net中相当常用,以下是控件的解释,有些是常用的,有些是偶尔用到的,查找.使用.记录,仅此而已.(最后附带DropDownList控件) ASP.NET中GridView ...
- Set up gradle HiveMind
HiveMind is a comprehensive ERP application for service organizations. It includes a project managem ...
- PowerDesigner-导出表到word
1. 在工具栏中选择[Report -->Reports],如下图 2. 点击第二个图标创建一个Report,如下图 该wizard中有三个信息 Report name Report : Rep ...
- BZOJ-1880 Elaxia的路线 SPFA+枚举
1880: [Sdoi2009]Elaxia的路线 Time Limit: 4 Sec Memory Limit: 64 MB Submit: 921 Solved: 354 [Submit][Sta ...
- BZOJ2463 谁能赢呢?
Description 小明和小红经常玩一个博弈游戏.给定一个n×n的棋盘,一个石头被放在棋盘的左上角.他们轮流移动石头.每一回合,选手只能把石头向上,下,左,右四个方向移动一格,并且要求移动到的 ...
- BZOJ1093 最大半连通子图
Description 一个有向图G=(V,E)称为半连通的(Semi-Connected),如果满足:?u,v∈V,满足u→v或v→u,即对于图中任意 两点u,v,存在一条u到v的有向路径或者从v到 ...