// 遍历 (内部迭代)
Layui.prototype.each = function (obj, fn) {
var key;
var that = this;
var callFn = function (key, obj) { // 回调函数
return fn.call(obj[key], key, obj[key]);
};
// fn 不为 function 类型, 返回that
if(typeof fn !== 'function') return that;
// 优先处理数组结构
if(that._isArray(obj)){
for(key = 0; key < obj.length; key++){
// 返回 true 时, 不执行
if(callFn(key, obj)) break;
}
} else {
for(key in obj){
if(callFn(key, obj)) break;
}
}
return that;
};
可以看出each函数源码,还是非常简单的。总的运行如下图
迭代器模式概述: 迭代器模式是提供一种方法顺序访问一个聚合对象中的各个元素,而又不需要暴露该对象的内容表示.迭代器模式可以把迭代的过程从业务逻辑中分离出来,在使用迭代器模式之后,即使不关心对象的内部构造,也可以按顺序访问其中的每个元素.
迭代器一般分为两种: 内部迭代器和外部迭代器.layui.each函数是内部迭代器.
这里主要通过完整一个layui的each内部迭代器来展示如何书写迭代器,对于外部迭代器有兴趣的可以自行补充.
let each =function(ary, callback){
for(var i = 0, l = ary.length; i<l; i++){
callback.call(ary[i], i ,ary[i]); // this 显示绑定
}
}
each(['kh1', 'kh2', 'kh3'], function(index, item){
console.log('kh', index, item);
})
这里定义了一个简单的迭代数组的内部迭代器函数和layui中基本相似,与layui中不同之处在于layui中加入了迭代类数组对象和字面量对象功能和layui中特有判断.
可以看到each函数的内部已经定义好了迭代规则,它完全接手整个迭代过程,外部只需要一次初始调用.
加入迭代类数组对象和字面量对象迭代
let each =function(obj, callback){
var value;
var i = 0;
var length = obj.length;
var isArray = Array.isArray(obj);
if(isArray){
for(; i < length; i++){
value = callback.call(obj[i], i ,obj[i]);
if(!value) break;
}
} else {
for (i in obj){
value = callback.call(obj[i], i ,obj[i]);
if(!value) break;
}
}
}
each(['kh1', 'kh2', 'kh3'], function(index, item){
console.log('kh', index, item);
})
总结: 迭代器模式不是什么深奥的东西,jq, js等框架和语言中都内置了迭代器.除此之外不管是内部迭代器还是外部迭代器都有优缺点,应选择适合自己场景的迭代器.
源码github