Ruby's Louvre

每天学习一点点算法

导航

javascript 的forEach函数

在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 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));
      };
    };

posted on 2009-11-10 16:37  司徒正美  阅读(14799)  评论(4编辑  收藏  举报