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 相关文章推荐
[原创]来自ImageSee官方 JavaScript图片浏览器
Jan 16 Javascript
javascript的parseFloat()方法精度问题探讨
Nov 26 Javascript
JS区分浏览器页面是刷新还是关闭
Apr 17 Javascript
javaScript中的原型解析【推荐】
May 05 Javascript
js手动播放图片实现图片轮播效果
Sep 17 Javascript
BootStrap 表单控件之单选按钮水平排列
May 23 Javascript
实现微信小程序的wxml文件和wxss文件在webstrom的支持
Jun 12 Javascript
jQuery层级选择器_动力节点节点Java学院整理
Jul 04 jQuery
AngularJS 的$timeout服务示例代码
Sep 21 Javascript
layui表格checkbox选择全选样式及功能的实例
Mar 07 Javascript
node版本管理工具n包使用教程详解
Nov 09 Javascript
jQuery带控制按钮轮播图插件
Jul 31 jQuery
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 获取远程网页内容的代码(fopen,curl已测)
2011/06/06 PHP
php学习之function的用法
2012/07/14 PHP
PHP中执行cmd命令的方法
2014/10/11 PHP
PHP将URL转换成短网址的算法分享
2016/09/13 PHP
简单谈谈PHP中的trait
2017/02/25 PHP
ThinkPHP实现静态缓存和动态缓存示例代码
2017/05/02 PHP
PHP explode()函数用法讲解
2019/02/15 PHP
php 的多进程操作实践案例分析
2020/02/28 PHP
PhpSpreadsheet设置单元格常用操作汇总
2020/11/13 PHP
jquery 1.3.2 IE8中的一点点的小问题解决方法
2009/07/10 Javascript
Javascript 日期处理之时区问题
2009/10/08 Javascript
javascript 三种编解码方式
2010/02/01 Javascript
javaScript矢量图表库-gRaphael几行代码实现精美的条形图/饼图/点图/曲线图
2013/01/09 Javascript
JS通过相同的name进行表格求和代码
2013/08/18 Javascript
vue实现城市列表选择功能
2018/07/16 Javascript
了解前端理论:rscss和rsjs
2019/05/23 Javascript
Vue触发隐藏input file的方法实例详解
2019/08/14 Javascript
[49:21]2018DOTA2亚洲邀请赛3月30日 小组赛B组 Effect VS iG
2018/03/31 DOTA
教你如何将 Sublime 3 打造成 Python/Django IDE开发利器
2014/07/04 Python
Python应用库大全总结
2018/05/30 Python
python utc datetime转换为时间戳的方法
2019/01/15 Python
pyqt5 QProgressBar清空进度条的实例
2019/06/21 Python
使用python实现名片管理系统
2020/06/18 Python
pycharm 的Structure界面设置操作
2021/02/05 Python
Europcar德国:全球汽车租赁领域的领导者
2018/08/15 全球购物
Chinti & Parker官网:奢华羊绒女装和创新针织设计
2021/01/01 全球购物
如何判断一段程序是由C 编译程序还是由C++编译程序编译的
2013/08/04 面试题
关于赌博的检讨书
2014/01/24 职场文书
医务工作者先进事迹材料
2014/01/26 职场文书
航海技术专业毕业生求职信
2014/04/06 职场文书
经贸专业毕业生求职信范文
2014/05/01 职场文书
爱心捐书倡议书
2015/04/27 职场文书
国家助学金受助感言
2015/08/01 职场文书
会议承办单位欢迎词
2019/07/09 职场文书
vue3中的组件间通信
2021/03/31 Vue.js
Django路由层如何获取正确的url
2021/07/15 Python