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做拖动布局的思路
May 31 Javascript
js获取网页高度(详细整理)
Dec 28 Javascript
Json字符串转换为JS对象的高效方法实例
May 01 Javascript
jquery如何判断某元素是否具备指定的样式
Nov 05 Javascript
手机软键盘弹出时影响布局的解决方法
Dec 15 Javascript
Vue组件tree实现树形菜单
Apr 13 Javascript
基于vue+ bootstrap实现图片上传图片展示功能
May 17 Javascript
Bootstrap多级菜单的实现代码
May 23 Javascript
关于js的三种使用方式(行内js、内部js、外部js)的程序代码
May 05 Javascript
解决Layui选择全部,换页checkbox复选框重新勾选的问题方法
Aug 14 Javascript
微信小程序实现弹出菜单动画
Jun 21 Javascript
基于vue.js仿淘宝收货地址并设置默认地址的案例分析
Aug 20 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动态创建Web站点的方法
2011/08/14 PHP
PHP可变函数学习小结
2015/11/29 PHP
PHP获取用户访问IP地址的5种方法
2016/05/16 PHP
基于PHP实现的多元线性回归模拟曲线算法
2018/01/30 PHP
File文件控件,选中文件(图片,flash,视频)即立即预览显示
2009/04/09 Javascript
onsubmit阻止form表单提交与onclick的相关操作
2010/09/03 Javascript
兼容IE和Firefox火狐的上下、左右循环无间断滚动JS代码
2013/04/19 Javascript
jquery入门必备的基本认识及实例(整理)
2013/06/24 Javascript
javascript中取前n天日期的两种方法分享
2014/01/26 Javascript
详解Javascript 装载和执行
2014/11/17 Javascript
用JavaScript显示浏览器客户端信息的超相近教程
2015/06/18 Javascript
利用js编写响应式侧边栏
2016/09/17 Javascript
Angular2从搭建环境到开发步骤详解
2016/10/17 Javascript
基于MVC方式实现三级联动(JavaScript)
2017/01/23 Javascript
javascript checkbox/radio onchange不能兼容ie8处理办法
2017/06/13 Javascript
zTree异步加载展开第一级节点的实现方法
2017/09/05 Javascript
vue地址栏直接输入路由无效问题的解决
2018/11/15 Javascript
Vue 中 filter 与 computed 的区别与用法解析
2019/11/21 Javascript
你可能从未使用过的11+个JavaScript特性(小结)
2020/01/08 Javascript
Python之Scrapy爬虫框架安装及简单使用详解
2017/12/22 Python
使用pandas read_table读取csv文件的方法
2018/07/04 Python
利用Python对文件夹下图片数据进行批量改名的代码实例
2019/02/21 Python
Python3 Tensorlfow:增加或者减小矩阵维度的实现
2020/05/22 Python
html5教程画矩形代码分享
2013/12/04 HTML / CSS
HTML最新标准HTML5总结(必看)
2016/06/13 HTML / CSS
博朗(Braun)俄罗斯官方商店:德国小家电品牌
2019/09/24 全球购物
Linux机考试题
2015/10/16 面试题
大学毕业登记表自我鉴定
2013/10/09 职场文书
小学生志愿者活动方案
2014/08/23 职场文书
西湖英语导游词
2015/02/06 职场文书
个性发展自我评价2015
2015/03/09 职场文书
中秋节主题班会
2015/08/14 职场文书
2019员工保密协议书(3篇)
2019/09/23 职场文书
golang 比较浮点数的大小方式
2021/05/02 Golang
PostgreSQL13基于流复制搭建后备服务器的方法
2022/01/18 PostgreSQL
Windows Server 2019 域控制器安装图文教程
2022/04/28 Servers