Prototype源码浅析 Enumerable部分之each方法


Posted in Javascript onJanuary 16, 2012

在javascript中,根本找不到Enumerable的影子,因为这一块是Prototype作者从Ruby中借鉴过来的。并且Enumerable在实际中根本没有直接应用的机会,都是混入到其他的对象中,可以说是其他对象的一个“父类”(不过只是调用了Object的extend方法,进行了方法的直接拷贝而已)。

我并不熟悉Ruby,不过看Enumerable中的一些方法,倒是跟Python中的有几分相似。

Enumerable其中一个最重要的方法是each,each这个方法应该都比较熟悉,其作用便是遍历一个序列的所有元素,并进行相应的处理。不过多数是应用在数组上,比如原生数组的forEach方法,以及jQuery中的链式调用,都依赖于each方法。因为jQuery选择器返回的是一个DOM对象数组,然后再在返回的数组上来调用each,从而分别处理每一个元素。

一般each都有两个参数:一个是迭代处理的函数和方法对应的上下文。

var each = Array.prototype.forEach || function(iterator,context){ 
for(var i = 0,len = this.length ; i < len ; i++){ 
iterator.call(context,this[i],this); 
} 
};

按照上面的方法,我们给Array对象扩展一个打印当前所有元素的print方法。

Array.prototype.each = Array.prototype.forEach || function(iterator,context){ 
for(var i = 0,len = this.length ; i < len ; i++){ 
iterator.call(context,this[i],i,this); 
} 
}; 
Array.prototype.print = function(){ 
this.each(function(item){ 
console.log(item); 
}); 
} 
console.log([1,2,3,4].print());//1,2,3,4

在Enumerable中,each并没有对应到具体的方法,前面说过Enumerable并不之际应用,而是作为一个“父类”应用到其他的对象,因此它的each方法是调用“子类”_each方法,因此任何混入Enumerable模块的对象,都必须提供一个_each方法,作为作用于实际循环的迭代代码。

现在Array.prototype上实现一个_each方法和一个each方法,实现一:

Array.prototype.each = function(iterator,context){ 
this._each(iterator,context) 
} 
Array.prototype._each = function(iterator,context){ 
for(var i = 0,len = this.length ; i < len ; i++){ 
iterator.call(context,this[i],i,this); 
} 
};

按照先前说的,_each只需要提供一个iterator参数就可以了,不过由于_each也被扩展到Array.prototype上面,于是实现的时候也附带了context参数。因此在Enumerable中,并没有使用_each的第二个context参数,是否实现对each没有影响。因此上面的实现一 不应该依赖_each的context,于是修改each如下:

Array.prototype.each = function(iterator,context){ 
var index = 0; 
this._each(function(value){ 
iterator.call(context,value,index++); 
}) 
}

这样一来,each方法的独立性提高了,在后续的Hash中也可以使用这个Enumerable了。任何看遍历的对象,只要提供了_each方法,就可以从Enumerable这里获得相应的方法。

因此,将上面的print例子用Enumerable的形式来实现,便得到如下的结果:

var Enumerable = {}; 
Enumerable.each = function(iterator, context) { 
var index = 0; 
this._each(function(value){ 
iterator.call(context, value, index++); 
}); 
return this; 
}; 
Enumerable.print = function(){ 
this.each(function(item){ 
console.log(item); 
}) 
}; 
Array.prototype._each = function(iterator,context){ 
for(var i = 0,len = this.length ; i < len ; i++){ 
iterator.call(context,this[i],i,this); 
} 
}; 
//下面的实现源码中是用的extend方法 
for(var key in Enumerable){ 
Array.prototype[key] = Enumerable[key]; 
}; 
[1,2,3,4].print();//1,2,3,4

理解each的实现是理解Enumerable对象的关键,后面的Array和Hash都混入Enumerable对象,颇为重要。
转载请注明来自小西山子【http://www.cnblogs.com/xesam/】
Javascript 相关文章推荐
javascript 折半查找字符在数组中的位置(有序列表)
Dec 09 Javascript
关于二级域名下使用一级域名下的COOKIE的问题
Nov 07 Javascript
JavaScript面向对象(极简主义法minimalist approach)
Jul 17 Javascript
jQuery.extend()的实现方式详解及实例
Jun 29 Javascript
javascript调试之DOM断点调试法使用技巧分享
Apr 15 Javascript
jQuery实现返回顶部功能适合不支持js的浏览器
Aug 19 Javascript
深入理解JavaScript中的浮点数
May 18 Javascript
web打印小结
Jan 11 Javascript
ES6新特性之解构、参数、模块和记号用法示例
Apr 01 Javascript
Vue代码分割懒加载的实现方法
Nov 23 Javascript
完美解决iview 的select下拉框选项错位的问题
Mar 02 Javascript
对于防止按钮重复点击的尝试详解
Apr 22 Javascript
javascript椭圆旋转相册实现代码
Jan 16 #Javascript
Prototype源码浅析 Number部分
Jan 16 #Javascript
Prototype源码浅析 String部分(四)之补充
Jan 16 #Javascript
Prototype源码浅析 String部分(二)
Jan 16 #Javascript
深入理解JavaScript系列(11) 执行上下文(Execution Contexts)
Jan 15 #Javascript
深入理解JavaScript系列(10) JavaScript核心(晋级高手必读篇)
Jan 15 #Javascript
深入理解JavaScript系列(9) 根本没有“JSON对象”这回事!
Jan 15 #Javascript
You might like
用php写的serv-u的web申请账号的程序
2006/10/09 PHP
从零开始学YII2框架(二)通过 Composer 安装扩展插件
2014/08/20 PHP
php短网址和数字之间相互转换的方法
2015/03/13 PHP
微信公众号开发之获取位置信息php代码
2018/06/13 PHP
Nigma vs Liquid BO3 第一场2.14
2021/03/10 DOTA
获取URL地址中的文件名和参数的javascript代码
2009/09/02 Javascript
JS 精确统计网站访问量的实例代码
2013/07/05 Javascript
jquery 设置元素相对于另一个元素的top值(实例代码)
2013/11/06 Javascript
jquery实现pager控件示例
2014/04/09 Javascript
jQuery设置和获取HTML、文本和值示例
2014/07/08 Javascript
JQuery查找DOM节点的方法
2015/06/11 Javascript
jquery中val()方法是从最后一个选项往前读取的
2015/09/06 Javascript
JS加载iFrame出现空白问题的解决办法
2016/05/13 Javascript
C#微信小程序服务端获取用户解密信息实例代码
2017/03/10 Javascript
javascript回调函数的概念理解与用法分析
2017/05/27 Javascript
js实现图片上传预览原理分析
2017/07/13 Javascript
关于HTML5的data-*自定义属性的总结
2018/05/05 Javascript
PHPStorm中如何对nodejs项目进行单元测试详解
2019/02/28 NodeJs
[03:04]2018年度DOTA2玩家最喜爱的主播-完美盛典
2018/12/16 DOTA
python中pycurl库的用法实例
2014/09/30 Python
python操作ssh实现服务器日志下载的方法
2015/06/03 Python
Ruby使用eventmachine为HTTP服务器添加文件下载功能
2016/04/20 Python
Python输出由1,2,3,4组成的互不相同且无重复的三位数
2018/02/01 Python
设置python3为默认python的方法
2018/10/31 Python
Python+OpenCV图片局部区域像素值处理详解
2019/01/23 Python
Python3+OpenCV2实现图像的几何变换(平移、镜像、缩放、旋转、仿射)
2019/05/13 Python
找Python安装目录,设置环境路径以及在命令行运行python脚本实例
2020/03/09 Python
Original Penguin美国官网:布拉德皮特、强尼德普喜爱的服装品牌
2016/10/25 全球购物
德国药房apodiscounter中文官网:德国排名前三的网上药店
2019/06/03 全球购物
澳大利亚在线床零售商:Bedworks
2020/09/01 全球购物
怎么可以提高数据库查询数据的速度
2014/06/28 面试题
护士自荐信怎么写
2013/10/18 职场文书
仓库管理专业个人的自我评价
2013/12/30 职场文书
幼儿园保育员岗位职责
2014/04/13 职场文书
入党培养人考察意见
2015/06/08 职场文书
公务员廉洁从政心得体会
2016/01/19 职场文书