src/compile/blocks.js
function(block) {

      var ast = block[0];
      var _from = this.getLiteral(ast.from);
      var _block = block.slice(1);
      var _to = ast.to;
      var local = {
        foreach: {
          count: 0
        }
      };
      var ret = '';
      var guid = utils.guid();
      var contextId = 'foreach:' + guid;

      var type = ({}).toString.call(_from);
      if (!_from || (type !== '[object Array]' && type !== '[object Object]')) {
        return '';
      }

      if (utils.isArray(_from)) {
        var len = _from.length;
        utils.forEach(_from, function(val, i) {
          if (this._state.break) {
            return;
          }
          // 构造临时变量
          local[_to] = val;
          local.foreach = {
            count: i + 1,
            index: i,
            hasNext: i + 1 < len
          };
          local.velocityCount = i + 1;

          this.local[contextId] = local;
          ret += this._render(_block, contextId);

        }, this);
      } else {
        var len = utils.keys(_from).length;
        utils.forEach(utils.keys(_from), function(key, i) {
          if (this._state.break) {
            return;
          }
          local[_to] = _from[key];
          local.foreach = {
            count: i + 1,
            index: i,
            hasNext: i + 1 < len
          };
          local.velocityCount = i + 1;
          this.local[contextId] = local;
          ret += this._render(_block, contextId);
        }, this);
      }

      // if foreach items be an empty array, then this code will shift current
      // conditions, but not this._render call, so this will shift parent context
      if (_from && _from.length) {
        this._state.break = false;
        // empty current local context object
        this.local[contextId] = {};
        this.conditions.shift();
        this.condition = this.conditions[0] || '';
      }

      return ret;

    }
function(block) {

      var ast = block[0];
      var _from = this.getLiteral(ast.from);
      var _block = block.slice(1);
      var _to = ast.to;
      var local = {
        foreach: {
          count: 0
        }
      };
      var ret = '';
      var guid = utils.guid();
      var contextId = 'foreach:' + guid;

      var type = ({}).toString.call(_from);
      if (!_from || (type !== '[object Array]' && type !== '[object Object]')) {
        return '';
      }

      if (utils.isArray(_from)) {
        var len = _from.length;
        utils.forEach(_from, function(val, i) {
          if (this._state.break) {
            return;
          }
          // 构造临时变量
          local[_to] = val;
          local.foreach = {
            count: i + 1,
            index: i,
            hasNext: i + 1 < len
          };
          local.velocityCount = i + 1;

          this.local[contextId] = local;
          ret += this._render(_block, contextId);

        }, this);
      } else {
        var len = utils.keys(_from).length;
        utils.forEach(utils.keys(_from), function(key, i) {
          if (this._state.break) {
            return;
          }
          local[_to] = _from[key];
          local.foreach = {
            count: i + 1,
            index: i,
            hasNext: i + 1 < len
          };
          local.velocityCount = i + 1;
          this.local[contextId] = local;
          ret += this._render(_block, contextId);
        }, this);
      }

      // if foreach items be an empty array, then this code will shift current
      // conditions, but not this._render call, so this will shift parent context
      if (_from && _from.length) {
        this._state.break = false;
        // empty current local context object
        this.local[contextId] = {};
        this.conditions.shift();
        this.condition = this.conditions[0] || '';
      }

      return ret;

    }
function ( block ) { var ast = block [ 0 ] ; var _from = this . getLiteral ( ast . from ) ; var _block = block . slice ( 1 ) ; var _to = ast . to ; var local = { foreach : { count : 0 } } ; var ret = '' ; var guid = utils . guid ( ) ; var contextId = 'foreach:' + guid ; var type = ( { } ) . toString . call ( _from ) ; if ( ! _from || ( type !== '[object Array]' && type !== '[object Object]' ) ) { return '' ; } if ( utils . isArray ( _from ) ) { var len = _from . length ; utils . forEach ( _from , function ( val , i ) { if ( this . _state . break ) { return ; } // 构造临时变量 local [ _to ] = val ; local . foreach = { count : i + 1 , index : i , hasNext : i + 1 < len } ; local . velocityCount = i + 1 ; this . local [ contextId ] = local ; ret += this . _render ( _block , contextId ) ; } , this ) ; } else { var len = utils . keys ( _from ) . length ; utils . forEach ( utils . keys ( _from ) , function ( key , i ) { if ( this . _state . break ) { return ; } local [ _to ] = _from [ key ] ; local . foreach = { count : i + 1 , index : i , hasNext : i + 1 < len } ; local . velocityCount = i + 1 ; this . local [ contextId ] = local ; ret += this . _render ( _block , contextId ) ; } , this ) ; } // if foreach items be an empty array, then this code will shift current // conditions, but not this._render call, so this will shift parent context if ( _from && _from . length ) { this . _state . break = false ; // empty current local context object this . local [ contextId ] = { } ; this . conditions . shift ( ) ; this . condition = this . conditions [ 0 ] || '' ; } return ret ; }
parse #foreach
parse #foreach