javascript forEach通用循环遍历方法


Posted in Javascript onOctober 11, 2010

上一次的错误太多,排版也出现了问题,重写了一遍,希望大家支持.

循环遍历一个元素是开发中最常见的需求之一,那么让我们来看一个由框架BASE2和Jquery的结合版本吧.

var forEach = (function(){
  //数组与伪数组的遍历
  var _Array_forEach = function (array, block, context) { 
    if (array == null) return; 
    //对String进行特殊处理
    if(typeof array == 'string'){
      array = array.split('');
    }
    var i = 0,length = array.length; 
    for (;i < length && block.call(context, array[i], (i+1), array)!==false; i++) {}  
  }; 
  //对象的遍历
  var _Function_forEach = function (object, block, context) { 
    for (var key in object) { 
      //只遍历本地属性 
      if (object.hasOwnProperty(key)&&block.call(context, object[key], key, object)===false){
        break;
      }
    } 
  }; 
  return function(object, block, context){
    if (object == null) return; 
    if (typeof object.length == "number") { 
     _Array_forEach(object, block, context); 
    }else{  
      _Function_forEach(object, block, context); 
    }
  };
})()

函数本身并不复杂,但很精巧。加了一些简单的注释,想信大家能看懂。

来看一点例子

//1:1  \n 2:2 
forEach([1,2,3,4,5],function(el,index){
  if(index>2){
    return false;
  }
  alert(index+":"+el);
});
 
function print(el,index){
  alert(index+":"+el);
}
//a:a  \n b:b   \n c:c
forEach({a:'a',b:'b',c:'c'},print);
 
//1:笨  \n 2:蛋   \n 3:的   \n 4:座   \n 5:右   \n 6:铭
forEach("笨蛋的座右铭",print);
   
function Person(name, age) { 
 this.name = name || ""; 
 this.age = age || 0; 
}; 
Person.prototype = new Person; 
var fred = new Person("笨蛋的座右铭", 25); 
fred.language = "chinese";//极晚绑定 
//name:jxl \n age:22 \n language:chinese
forEach(fred,print);

注:回调函数中的index参数下标从1开始

为什么不用内置的forEach

和getElementsByClassName一样,内置的forEach效率很高,但是在功能上有局限性,它无法在循环中途退出。而在我们这个forEach中,它可以在处理函数内通过返回false的方式退出循环,更加的灵活。

特别的length属性

length属性是一个很特别的属性,看到数组,大家一定会想到length,那看到带有length属性的对象呢?那大家一定要想到伪数组(类数组)。那什么是伪数组呢?简单的理解就是能通过Array.prototype.slice转换为真正的数组的带有length属性的对象。javascript最为著名的伪数组就是arguments对象。关于伪数组有很多东西,以后我会专门写一篇博文讲这个东西。大家只要记住:不要随便给对象赋予length属性,除非你明确的知道,你准备把它当作伪数组来使用。

我想这个函数是一个简单javascript工具库中的必备函数,它是金字塔的根基,在它的基础上,进行再封装,可以让你的库更强大,更加美丽!

以下是补充

在Base2中找到一个叫forEach的函数,是我见过的最好的实现。挖出来分析一下。它能对各种普通对象,字符串,数组以及类数组进行遍历。如果原游览器的对象已实现此函数,它则调用原对象的函数。

function forEach(object, block, context, fn) {
 if (object == null) return;
 if (!fn) {
  if (typeof object == "function" && object.call) {
   //遍历普通对象
   fn = Function;
  } else if (typeof object.forEach == "function" && object.forEach != arguments.callee) {
   //如果目标已经实现了forEach方法,则使用它自己的forEach方法(如标准游览器的Array对象)
   object.forEach(block, context);
   return;
  } else if (typeof object.length == "number") {
   // 如果是类数组对象或IE的数组对象
   _Array_forEach(object, block, context);
   return;
  }
 }
 _Function_forEach(fn || Object, object, block, context);
};
 
function _Array_forEach(array, block, context) {
 if (array == null) return;
 var i = 0,length = array.length;
 if (typeof array == "string") {
  for (; i < length; i++) {
   block.call(context, array.charAt(i), i, array);
  }
 }else{
  for (;i < length; i++) {
   block.call(context, array[i], i, array);
  }
 }
};
 
 
 _Function_forEach = function(fn, object, block, context) {
  // 这里的fn恒为Function
  for (var key in object) {
    //只遍历本地属性
    if (object.hasOwnProperty(key)) {
    //相当于 block(object[key], key)
    block.call(context, object[key], key, object);
   }
  }
 };

原作者的一些例子(我FQ扒过来了!):

function print(el,index){
 alert(index+" : "+el)
}
forEach ([1, 2, 3], print);
forEach ({a: "aa", b: "bb",c: "cc"}, print);
forEach ("司徒正美", print);
forEach(document.styleSheets,function(el){
 if(el.href) alert(el.href)
});

司徒正美的

function forEach(object, block, context, fn) {
   if (object == null) return;
   if (!fn) {
    if (typeof object == "function" && object.call) {
     //遍历普通对象
     fn = Function;
    } else if (typeof object.forEach == "function" && object.forEach != arguments.callee) {
     //如果目标已经实现了forEach方法,则使用它自己的forEach方法(如标准游览器的Array对象)
     object.forEach(block, context);
     return;
    } else if (typeof object.length == "number") {
     // 如果是类数组对象或IE的数组对象
     _Array_forEach(object, block, context);
     return;
    }
   }
   _Function_forEach(fn || Object, object, block, context);
  };

  function _Array_forEach(array, block, context) {
   if (array == null) return;
   var i = 0,length = array.length;
   if (typeof array == "string")
    array = array.split("");
   for (;i < length; i++) {
    block.call(context, array[i], i, array);
   }
 };


  _Function_forEach = function(fn, object, block, context) {
   // 这里的fn恒为Function
   for (var key in object) {
     //只遍历本地属性
     if (object.hasOwnProperty(key)) {
     //相当于 block(object[key], key)
     block.call(context, object[key], key, object);
    }
   }
  };
 

 function print(el,index){
  alert(index+" : "+el)
 }
 forEach ([1, 2, 3], print);
 forEach ({a: "aa", b: "bb",c: "cc"}, print);
 forEach ("司徒正美", print);
 forEach(document.styleSheets,function(el){
  if(el.href) alert(el.href)
 });

代码

function Person(name, age) {
 this.name = name || "";
 this.age = age || 0;
};
 
 
var fred = new Person("Fred", 38);
fred.language = "English";//极晚绑定
fred.wife = "Wilma";//极晚绑定
forEach(fred,print)

完整代码

function forEach(object, block, context, fn) {
   if (object == null) return;
   if (!fn) {
    if (typeof object == "function" && object.call) {
     //遍历普通对象
     fn = Function;
    } else if (typeof object.forEach == "function" && object.forEach != arguments.callee) {
     //如果目标已经实现了forEach方法,则使用它自己的forEach方法(如标准游览器的Array对象)
     object.forEach(block, context);
     return;
    } else if (typeof object.length == "number") {
     // 如果是类数组对象或IE的数组对象
     _Array_forEach(object, block, context);
     return;
    }
   }
   _Function_forEach(fn || Object, object, block, context);
  };

  function _Array_forEach(array, block, context) {
   if (array == null) return;
   var i = 0,length = array.length;
   if (typeof array == "string")
    array = array.split("");
   for (;i < length; i++) {
    block.call(context, array[i], i, array);
   }
 };

 
  _Function_forEach = function(fn, object, block, context) {
   // 这里的fn恒为Function
   for (var key in object) {
    //只遍历本地属性
     if (object.hasOwnProperty(key)) {
     //相当于 block(object[key], key)
     block.call(context, object[key], key, object);
    }
   }
  };
 
 function print(el,index){
  alert(index+" : "+el)
 }
   function Person(name, age) {
   this.name = name || "";
   this.age = age || 0;
  };
 
  
  var fred = new Person("Fred", 38);
  fred.language = "English";//极晚绑定
  fred.wife = "Wilma";//极晚绑定
  forEach(fred,print)

在Base2中还提供了一个叫unbind的方法,我们可以用它把原生对象的forEach方法剥离出来供我们调用:

核心代码

var _slice = Array.prototype.slice;
function unbind(fn) {
 return function(context) {
  return fn.apply(context, _slice.call(arguments, 1));
 };
};

完整代码

try{
 var _slice = Array.prototype.slice;
  function unbind(fn) {
   return function(context) {
    return fn.apply(context, _slice.call(arguments, 1));
   };
  };
  function print(el,index){
   alert(index+" : "+el)
  }
  var each = unbind(Array.prototype["forEach"])
  var a = {cc : function(e){alert(e)}};
  each(["11111","22222"],a.cc,a)//最后的a可有可无
}catch(e){alert("请在标准浏览器中使用!")}

这篇文章就介绍到这了,希望大家以后多多支持三水点靠木。

Javascript 相关文章推荐
入门基础学习 ExtJS笔记(一)
Nov 11 Javascript
JS date对象的减法处理实现代码
Dec 28 Javascript
jQuery数组处理代码详解(含实例演示)
Feb 03 Javascript
关于ExtJS4.1:快捷键支持的问题
Apr 24 Javascript
jQuery实现的向下图文信息滚动效果
May 03 Javascript
JavaScript实现弹出DIV层同时页面背景渐变成半透明效果
Mar 25 Javascript
浅谈jQuery 选择器和dom操作
Jun 07 Javascript
基于jQuery下拉选择框插件支持单选多选功能代码
Jun 07 Javascript
AngularJS 依赖注入详解和简单实例
Jul 28 Javascript
AngularJS 自定义指令详解及示例代码
Aug 17 Javascript
JavaScript创建对象的常用方式总结
Aug 10 Javascript
基于Echarts图表在div动态切换时不显示的解决方式
Jul 20 Javascript
JavaScript 操作键盘的Enter事件(键盘任何事件),兼容多浏览器
Oct 11 #Javascript
JavaScript isArray()函数判断对象类型的种种方法
Oct 11 #Javascript
JSChart轻量级图形报表工具(内置函数中文参考)
Oct 11 #Javascript
jQuery 表单验证扩展代码(一)
Oct 11 #Javascript
AlertBox 弹出层信息提示框效果实现步骤
Oct 11 #Javascript
基于jQuery的实现简单的分页控件
Oct 10 #Javascript
JQuery的Alert消息框插件使用介绍
Oct 09 #Javascript
You might like
php 获取文件行数的方法总结
2016/10/11 PHP
PHP5.5新特性之yield理解与用法实例分析
2019/01/11 PHP
关于Yii2框架跑脚本时内存泄漏问题的分析与解决
2019/12/01 PHP
PHP7生产环境队列Beanstalkd用法详解
2020/05/19 PHP
JS 获取select(多选下拉)中所选值的示例代码
2013/08/02 Javascript
jQuery中的read和JavaScript中的onload函数的区别
2014/08/27 Javascript
分享33个jQuery与CSS3实现的绚丽鼠标悬停效果
2014/12/15 Javascript
jquery实现多条件筛选特效代码分享
2015/08/28 Javascript
Labelauty?jQuery单选框/复选框美化插件分享
2015/09/26 Javascript
手机Web APP如何实现分享多平台功能
2016/08/19 Javascript
微信小程序 页面跳转和数据传递实例详解
2017/01/19 Javascript
基于JS实现仿京东搜索栏随滑动透明度渐变效果
2017/07/10 Javascript
php register_shutdown_function函数详解
2017/07/23 Javascript
[00:32]2016完美“圣”典风云人物:Maybe宣传片
2016/12/05 DOTA
[00:31]DOTA2荣耀之路7:Miracle-空血无敌斩
2018/05/31 DOTA
Python深入学习之上下文管理器
2014/08/31 Python
Python中用Descriptor实现类级属性(Property)详解
2014/09/18 Python
解析Python中的变量、引用、拷贝和作用域的问题
2015/04/07 Python
Python学习笔记基本数据结构之序列类型list tuple range用法分析
2019/06/08 Python
Pyqt清空某一个QTreeewidgetItem下的所有分支方法
2019/06/17 Python
tensorflow之tf.record实现存浮点数数组
2020/02/17 Python
python GUI编程(Tkinter) 创建子窗口及在窗口上用图片绘图实例
2020/03/04 Python
html5 兼容IE6结构的实现代码
2012/05/14 HTML / CSS
Tirendo比利时:在线购买轮胎
2018/10/22 全球购物
SEPHORA丝芙兰捷克官网:购买香水、化妆品和护肤品
2018/11/26 全球购物
应届生英语教师求职信
2013/11/05 职场文书
创建服务型党组织实施方案
2014/02/25 职场文书
小学六一儿童节活动方案
2014/08/27 职场文书
党员民主评议自我评价
2014/10/20 职场文书
小学教师年度个人总结
2015/02/05 职场文书
2015年女生节活动总结
2015/02/27 职场文书
校长个人总结
2015/03/03 职场文书
个人总结格式范文
2015/03/09 职场文书
观看《信仰》心得体会
2016/01/15 职场文书
只需要这一行代码就能让python计算速度提高十倍
2021/05/24 Python
windows server2016安装oracle 11g的图文教程
2022/07/15 Servers