src/compile/references.js
function(property, baseRef, ast) {

      var id = property.id;
      var ret = '';

      // getter 处理
      if (id.indexOf('get') === 0 && !(id in baseRef)) {
        if (id.length === 3) {
          // get('address')
          ret = getter(baseRef, this.getLiteral(property.args[0]));
        } else {
          // getAddress()
          ret = getter(baseRef, id.slice(3));
        }

        return ret;

      // setter 处理
      } else if (id.indexOf('set') === 0 && !baseRef[id]) {

        baseRef[id.slice(3)] = this.getLiteral(property.args[0]);
        // $page.setName(123)
        baseRef.toString = function() { return ''; };
        return baseRef;

      } else if (id.indexOf('is') === 0 && !(id in baseRef)) {

        return getter(baseRef, id.slice(2));
      } else if (id === 'keySet' && !baseRef[id]) {

        return utils.keys(baseRef);

      } else if (id === 'entrySet' && !baseRef[id]) {

        ret = [];
        utils.forEach(baseRef, function(value, key) {
          ret.push({key: key, value: value});
        });

        return ret;

      } else if (id === 'size' && !baseRef[id]) {

        return getSize(baseRef);
      } else if (id === 'put' && !baseRef[id]) {
        return baseRef[this.getLiteral(property.args[0])] = this.getLiteral(property.args[1]);
      } else if (id === 'add' && !baseRef[id] && typeof baseRef.push === 'function') {
        return baseRef.push(this.getLiteral(property.args[0]));
      } else if (id === 'subList' && !baseRef[id]) {
        return baseRef.slice(this.getLiteral(property.args[0]), this.getLiteral(property.args[1]));
      } else {

        ret = baseRef[id];
        var args = [];

        utils.forEach(property.args, function(exp) {
          args.push(this.getLiteral(exp));
        }, this);

        if (ret && ret.call) {

          var that = this;

          if(typeof baseRef === 'object' && baseRef){
            baseRef.eval = function() {
              return that.eval.apply(that, arguments);
            };
          }

          try {
            ret = ret.apply(baseRef, args);
          } catch (e) {
            var pos = ast.pos;
            var text = Velocity.Helper.getRefText(ast);
            var err = ' on ' + text + ' at L/N ' +
              pos.first_line + ':' + pos.first_column;
            e.name = '';
            e.message += err;
            throw new Error(e);
          }

        } else {
          this._throw(ast, property, 'TypeError');
          ret = undefined;
        }
      }

      return ret;
    }
function(property, baseRef, ast) {

      var id = property.id;
      var ret = '';

      // getter 处理
      if (id.indexOf('get') === 0 && !(id in baseRef)) {
        if (id.length === 3) {
          // get('address')
          ret = getter(baseRef, this.getLiteral(property.args[0]));
        } else {
          // getAddress()
          ret = getter(baseRef, id.slice(3));
        }

        return ret;

      // setter 处理
      } else if (id.indexOf('set') === 0 && !baseRef[id]) {

        baseRef[id.slice(3)] = this.getLiteral(property.args[0]);
        // $page.setName(123)
        baseRef.toString = function() { return ''; };
        return baseRef;

      } else if (id.indexOf('is') === 0 && !(id in baseRef)) {

        return getter(baseRef, id.slice(2));
      } else if (id === 'keySet' && !baseRef[id]) {

        return utils.keys(baseRef);

      } else if (id === 'entrySet' && !baseRef[id]) {

        ret = [];
        utils.forEach(baseRef, function(value, key) {
          ret.push({key: key, value: value});
        });

        return ret;

      } else if (id === 'size' && !baseRef[id]) {

        return getSize(baseRef);
      } else if (id === 'put' && !baseRef[id]) {
        return baseRef[this.getLiteral(property.args[0])] = this.getLiteral(property.args[1]);
      } else if (id === 'add' && !baseRef[id] && typeof baseRef.push === 'function') {
        return baseRef.push(this.getLiteral(property.args[0]));
      } else if (id === 'subList' && !baseRef[id]) {
        return baseRef.slice(this.getLiteral(property.args[0]), this.getLiteral(property.args[1]));
      } else {

        ret = baseRef[id];
        var args = [];

        utils.forEach(property.args, function(exp) {
          args.push(this.getLiteral(exp));
        }, this);

        if (ret && ret.call) {

          var that = this;

          if(typeof baseRef === 'object' && baseRef){
            baseRef.eval = function() {
              return that.eval.apply(that, arguments);
            };
          }

          try {
            ret = ret.apply(baseRef, args);
          } catch (e) {
            var pos = ast.pos;
            var text = Velocity.Helper.getRefText(ast);
            var err = ' on ' + text + ' at L/N ' +
              pos.first_line + ':' + pos.first_column;
            e.name = '';
            e.message += err;
            throw new Error(e);
          }

        } else {
          this._throw(ast, property, 'TypeError');
          ret = undefined;
        }
      }

      return ret;
    }
function ( property , baseRef , ast ) { var id = property . id ; var ret = '' ; // getter 处理 if ( id . indexOf ( 'get' ) === 0 && ! ( id in baseRef ) ) { if ( id . length === 3 ) { // get('address') ret = getter ( baseRef , this . getLiteral ( property . args [ 0 ] ) ) ; } else { // getAddress() ret = getter ( baseRef , id . slice ( 3 ) ) ; } return ret ; // setter 处理 } else if ( id . indexOf ( 'set' ) === 0 && ! baseRef [ id ] ) { baseRef [ id . slice ( 3 ) ] = this . getLiteral ( property . args [ 0 ] ) ; // $page.setName(123) baseRef . toString = function ( ) { return '' ; } ; return baseRef ; } else if ( id . indexOf ( 'is' ) === 0 && ! ( id in baseRef ) ) { return getter ( baseRef , id . slice ( 2 ) ) ; } else if ( id === 'keySet' && ! baseRef [ id ] ) { return utils . keys ( baseRef ) ; } else if ( id === 'entrySet' && ! baseRef [ id ] ) { ret = [ ] ; utils . forEach ( baseRef , function ( value , key ) { ret . push ( { key : key , value : value } ) ; } ) ; return ret ; } else if ( id === 'size' && ! baseRef [ id ] ) { return getSize ( baseRef ) ; } else if ( id === 'put' && ! baseRef [ id ] ) { return baseRef [ this . getLiteral ( property . args [ 0 ] ) ] = this . getLiteral ( property . args [ 1 ] ) ; } else if ( id === 'add' && ! baseRef [ id ] && typeof baseRef . push === 'function' ) { return baseRef . push ( this . getLiteral ( property . args [ 0 ] ) ) ; } else if ( id === 'subList' && ! baseRef [ id ] ) { return baseRef . slice ( this . getLiteral ( property . args [ 0 ] ) , this . getLiteral ( property . args [ 1 ] ) ) ; } else { ret = baseRef [ id ] ; var args = [ ] ; utils . forEach ( property . args , function ( exp ) { args . push ( this . getLiteral ( exp ) ) ; } , this ) ; if ( ret && ret . call ) { var that = this ; if ( typeof baseRef === 'object' && baseRef ) { baseRef . eval = function ( ) { return that . eval . apply ( that , arguments ) ; } ; } try { ret = ret . apply ( baseRef , args ) ; } catch ( e ) { var pos = ast . pos ; var text = Velocity . Helper . getRefText ( ast ) ; var err = ' on ' + text + ' at L/N ' + pos . first_line + ':' + pos . first_column ; e . name = '' ; e . message += err ; throw new Error ( e ) ; } } else { this . _throw ( ast , property , 'TypeError' ) ; ret = undefined ; } } return ret ; }
$foo.bar()求值
$foo . bar () 求值