san.js源码解读之模版解析(parseTemplate)篇——readCall函数

相关文章 san.js源码解读之模版解析(parseTemplate)篇——readAccessor函数

一、源码分析

/**
 * 读取调用
 *
 * @param {Walker} walker 源码读取对象
 * @param {Array=} defaultArgs 默认参数
 * @return {Object}
 */
function readCall(walker, defaultArgs) {
    walker.goUntil(); // 向前读取字符,直到遇到指定字符再停止
    var result = readAccessor(walker); // 读取访问表达式

    var args;
    if (walker.goUntil(40)) { // (   判断是否遇到 '(', 如果遇到进入下面处理
        args = [];

        while (!walker.goUntil(41)) { // ) 判断是否遇到')',它是跳出循环的判断条件
            args.push(readTertiaryExpr(walker)); // 因为在处理函数调用时,会遇到复杂的表达式,所以调用 readTertiaryExpr 函数来处理出现所以表达式的可能
            walker.goUntil(44); // ,
        }
    }
    else if (defaultArgs) {
        args = defaultArgs; // 如果有默认参数时,直接赋值 args。这里比较好理解,因为上面的操作就是解析函数参数的。
    }

    if (args) {
        result = {
            type: ExprType.CALL,
            name: result, // 把之前解析到的访问表达式,放入对象中并起名 name
            args: args
        };
    }

    return result; // 返回结果
}

在 san.js 中 readCall 函数是用来解析函数调用的。比如

<p>{{max(num1, num2)}}</p>

readCall 函数接收两个参数:walker 和 defaultArgs。

  1. walker 是 Walk 类的实例,它是源码读取对象
  2. defaultArgs 是默认参数,就是调用函数是传入的参数。比如 max(num1, num2) 中的 ’num1‘ 和 ‘num2’

当执行 readCall 函数时,首先执行 goUntil() 函数用来跳过空格、制表符、\r、\n之类的。goUntil 函数源码如下

/**
 * 向前读取字符,直到遇到指定字符再停止
 * 未指定字符时,当遇到第一个非空格、制表符的字符停止
 *
 * @param {number=} charCode 指定字符的code
 * @return {boolean} 当指定字符时,返回是否碰到指定的字符
 */
Walker.prototype.goUntil = function (charCode) {
    var code;
    while (this.index < this.len && (code = this.source.charCodeAt(this.index))) {
        switch (code) {
            case 32: // 空格 space
            case 9: // 制表符 tab
            case 13: // \r
            case 10: // \n
                this.index++;
                break;

            default:
                if (code === charCode) {
                    this.index++;
                    return 1;
                }
                return;
        }
    }
};

可以看出 goUntil 接受一个变量 charCode, 当传入该变量时或判断当前字符是否为传入的字符,如果时就返回 1并跳出循环,否者跳出循环。
接着调用 readAccessor 函数获取当前访问表达式并返回结果,然后向下面判断是否遇到‘(’,如果遇到就开始匹配括号内的参数,代码如下

if (walker.goUntil(40)) { // (   判断是否遇到 '(', 如果遇到进入下面处理
       args = [];

       while (!walker.goUntil(41)) { // ) 判断是否遇到')',它是跳出循环的判断条件
           args.push(readTertiaryExpr(walker)); // 因为在处理函数调用时,会遇到复杂的表达式,所以调用 readTertiaryExpr 函数来处理出现所以表达式的可能
           walker.goUntil(44); // ,
       }
  }

如果没有遇到,接着判断有没有传入默认参数,有的话就直接把默认参数赋值给 args,最后返回属于调用函数类型的对象结果

你可能感兴趣的:(san.js,javascript,前端,开发语言,san.js,源码分析)