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

news2024/11/27 4:21:29

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

一、源码分析

/**
 * 读取访问表达式
 *
 * @param {Walker} walker 源码读取对象
 * @return {Object}
 */
function readAccessor(walker) {
    var firstSeg = readIdent(walker);

    switch (firstSeg) { // 判断标识符
        case 'true':
        case 'false':
            return { // 遇到布尔值直接返回
                type: ExprType.BOOL,
                value: firstSeg === 'true', // 和字符串 'true' 直接判断返回布尔值
            };
        case 'null':
            return {
                type: ExprType.NULL
            };
    }

    var result = {
        type: ExprType.ACCESSOR, // 当前类型
        paths: [
            {type: ExprType.STRING, value: firstSeg}
        ]
    };

    /* eslint-disable no-constant-condition */

    // 对象访问有两种形式
    // 1: 点符号 - 在JavaScript中访问对象属性的一种常见方式是通过点符号。这涉及到在对象名称之后指定属性名称,两者之间用一个点隔开。
    // 例如:const name = {
    //   firstName: "Surbhi",
    //   lastName: "Dighe
    //  };
    // console.log(name.firstName);  // Output: "Surbhi"
    // 2: 括号符号 - 另一种访问对象属性的方法是通过括号符号,这涉及到将属性名称指定为方括号内的字符串
    // 例如:console.log(name["firstName"]);  // Output: "Surbhi"
    accessorLoop: while (1) {
    /* eslint-enable no-constant-condition */

        switch (walker.source.charCodeAt(walker.index)) {
            case 46: // .    当遇到 '.' 说明变量访问是 'person.job' 或者 'person[1].job' 之类的变量访问
                 walker.index++; // 向前移动,移过 '.'

                // ident as string
                // 因为遇到了 '.' 说明下面一定是一个变量名,所以使用 readIdent 进行解析
                result.paths.push({
                    type: ExprType.STRING,
                    value: readIdent(walker)
                });
                break;

            case 91: // [  当遇到 '[' 说明当前正处于 'person[]'
                walker.index++; // 向前移动,移过 '['
                result.paths.push(readTertiaryExpr(walker)); // 调用 readTertiaryExpr 进行匹配, 这是因为 '[]' 中可以有其他表达式,比如 'person[ index === 1 ? 1 : 0]' 或者 'person[name]'
                walker.goUntil(93); // ]
                break;

            default:
                break accessorLoop; // 默认跳出循环
        }
    }

    return result; // 返回匹配结果
}

在 javascript 中访问对象属性有两种方法分别如下
1: 点符号 - 在JavaScript中访问对象属性的一种常见方式是通过点符号。这涉及到在对象名称之后指定属性名称,两者之间用一个点隔开。
例如:

 		   const name = {
 		    firstName: "Surbhi",
 		    lastName: "Dighe
 		    };	
 	    	console.log(name.firstName);  // Output: "Surbhi"

2: 括号符号 - 另一种访问对象属性的方法是通过括号符号,这涉及到将属性名称指定为方括号内的字符串
例如:
console.log(name["firstName"]); // Output: "Surbhi"
在 readAccessor 中对属性访问的处理也是分这两种情况(但是需要了解的是‘person’单独变量在 readAccessor 函数中也是可以解析的,作为访问表达式,这也为什么readAccessor 函数的功能叫做读取访问表达式,而不是读取对象属性)。

首先通过 readIdent 函数解析出当前变量名,对变量名进行匹配如下

switch (firstSeg) { // 判断标识符
        case 'true':
        case 'false':
            return { // 遇到布尔值直接返回
                type: ExprType.BOOL,
                value: firstSeg === 'true', // 和字符串 'true' 直接判断返回布尔值
            };
        case 'null':
            return {
                type: ExprType.NULL
            };
    }

如果符合 ‘true’ 、‘false’和’null’,那么直接返回,后续不执行。那么什么时候遇到这种情况呐?比如 三元表达式时,匹配到‘true’或者‘false’就会走入该条件判断。

接着定义了访问符类型, 并且记录当前位置(value)

var result = {
      type: ExprType.ACCESSOR, // 当前类型
      paths: [
          {type: ExprType.STRING, value: firstSeg}
      ]
  };

然后对当前访问表达式进行循环匹配,当遇到 ‘.’ 时,说明是‘demo.job’ 这种情况,那么执行下面语句

case 46: // .    当遇到 '.' 说明变量访问是 'person.job' 或者 'person[1].job' 之类的变量访问
   walker.index++; // 向前移动,移过 '.'

   // ident as string
   // 因为遇到了 '.' 说明下面一定是一个变量名,所以使用 readIdent 进行解析
   result.paths.push({
       type: ExprType.STRING,
       value: readIdent(walker)
   });
   break;

当遇到‘[’时,说明是’demo[job]'、‘demo[index ? 1: 0]’ 、‘demo[‘true’]’等情况,那么执行面的语句

case 91: // [  当遇到 '[' 说明当前正处于 'person[]'
     walker.index++; // 向前移动,移过 '['
     result.paths.push(readTertiaryExpr(walker)); // 调用 readTertiaryExpr 进行匹配, 这是因为 '[]' 中可以有其他表达式,比如 'person[ index === 1 ? 1 : 0]' 或者 'person[name]'
     walker.goUntil(93); // ]
     break;

这里需要了解的是向 paths 数组中推入数据时调用了 readTertiaryExpr ,这是因为在‘[]’中可能有复杂的表达式,里面有变量数值等逻辑,所以需要从头解析。对于 readTertiaryExpr 函数内容后续会有介绍(解析表达式有点复杂,而且牵涉到嵌套、递归、解析先后顺序等逻辑)

当没有遇到‘.’或者‘[’, 那么走默认逻辑,直接跳出循环

default:
   break accessorLoop; // 默认跳出循环

二、示例: ‘person.job.one’

解析 ‘person.job.one’ 的结果
请添加图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1146599.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【论文复现:Active Learning via Local Structure Recontruction】

论文复现:Active Learning via Local Structure Reconstruction 目标函数优化过程公式(16)推到python代码链接如下: 目标函数 优化过程 公式(16)推到 原文中省略了上述推导过程 在这里我们自己推导一下,只要有一点数学基础就很简单&#xff…

【计算机网络】数据链路层——以太网

文章目录 前言什么是以太网以太网帧格式6位目的地址和源地址2位类型数据长度CRC 校验和 数据在数据链路层是如何转发的 前言 前面我们学习了关于应用层——自定义协议、传输层——UDP、TCP协议、网络层——IP协议,今天我将为大家分享关于数据链路层——以太网方面的…

基于蝙蝠算法的无人机航迹规划-附代码

基于蝙蝠算法的无人机航迹规划 文章目录 基于蝙蝠算法的无人机航迹规划1.蝙蝠搜索算法2.无人机飞行环境建模3.无人机航迹规划建模4.实验结果4.1地图创建4.2 航迹规划 5.参考文献6.Matlab代码 摘要:本文主要介绍利用蝙蝠算法来优化无人机航迹规划。 1.蝙蝠搜索算法 …

MAYA教程之灯光与渲染

灯光介绍 MAYA中有六种光源环境光:模拟环境中的光源,光线是四面八方的平行光:模拟太阳光点光源:模拟蜡烛等光源聚光灯:模拟夜场那种光源区域光:模拟窗户照进室内的光源体积光:模拟激光在MAYA的…

基于Java的流浪动物救助管理系统设计与实现(源码+lw+部署文档+讲解等)

文章目录 前言具体实现截图论文参考详细视频演示为什么选择我自己的网站自己的小程序(小蔡coding) 代码参考数据库参考源码获取 前言 💗博主介绍:✌全网粉丝10W,CSDN特邀作者、博客专家、CSDN新星计划导师、全栈领域优质创作者&am…

Generalised Zero-shot Learning with Multi-modal Embedding Spaces

分类器被 τ \tau τ校准 辅助信息 作者未提供代码

震惊!什么是测试用例?为什么要有测试用例?测试用例举例!测试用例竟然...被如此解释!

1、什么是测试用例 测试用例(Test Case)是为了实施测试而向被测试的系统提供的一组集合,这组集合包含:测试环境、操作步骤、测试数据、预期结果等要素。 生活举例: 大家有没有在牛客上刷题 牛客给大家提供了一套可以编…

【数据结构】排序算法总结

⭐ 作者:小胡_不糊涂 🌱 作者主页:小胡_不糊涂的个人主页 📀 收录专栏:浅谈数据结构 💖 持续更文,关注博主少走弯路,谢谢大家支持 💖 总结 1. 归并排序2. 排序算法复杂度…

C/C++跨平台构建工具CMake-----灵活添加库并实现开发和生产环境的分离

目录 1.概述2.创建项目3 配置运行项目3.1 编写开平方根示例代码3.2 编写CMake构建脚本 4.使用子模块实现求平方根的功能4.1 在子模块中实现两种求平方根的方法4.2 构建Mathfunctions子模块4.3 在根目录引用子模块的功能4.3.1 编写构建脚本4.3.2 编写C代码使用MathFunctions库中…

CNCC2023

中国工程院院士,之江实验室主任、阿里云创始人王坚:计算驱动的科学发现和科技创新。 国际计算机学会主席雅尼斯约阿尼迪斯(ACM President Yannis Ioannidis)。 电气和电子工程师协会计算机协会主席妮塔帕特尔(IEEE CS President Nita Patel)。 2022 I…

Python武器库开发-高级特性篇(九)

高级特性篇(九) 切片 在Python中,切片(slice)是对序列型对象(如list, string, tuple)的一种高级索引方法。普通索引只取出序列中一个下标对应的元素,而切片取出序列中一个范围对应的元素,这里的范围不是狭义上的连续片段。 要创建切片&…

SpringMVC系列-6 异常处理器

背景 本文作为 SpringMVC系列 的第六篇,介绍SpringMVC的异常处理器。内容包括异常处理器的使用方式、实现原理和内置异常处理器的装配过程。 1.使用方式 自定义异常类,用于异常处理器: public class ClientException extends RuntimeExce…

宝塔安装MySQL数据库,并内网穿透实现公网远程访问

宝塔安装MySQL数据库,并内网穿透实现公网远程访问 文章目录 宝塔安装MySQL数据库,并内网穿透实现公网远程访问前言1.Mysql服务安装2.创建数据库3.安装cpolar3.2 创建HTTP隧道 4.远程连接5.固定TCP地址5.1 保留一个固定的公网TCP端口地址5.2 配置固定公网…

操作系统——页表、快表 + 地址转化过程(王道视频p47、p48、p49)

1.页表的基本概念: (1)part1: (2)part2: (备注:默认——逻辑页 和 物理页 的页大小是相同的!!!) 2.在没有 快表的case下,进行逻辑地址 、 物理地址转换的流…

如何使用Codesys编程

在实际项目中,使用了两套TLC6伺服系统,不仅是因为TLC6具有电子凸轮功能,而且TLC6伺服驱动器内置PLC,使实现系统功能的编程更简单方便,且由于是内部编程,使系统响应更迅速。 TLC6内置PLC的编程环境为符合IEC…

C语言--输出格式控制(printf函数)

格式输出函数printf printf(格式控制,输出表列) 基本用法 格式字符功能例子d输出一个有符号的十进制整数printf("%d %d",12,-56);c输出一个字符 char ch a; printf("%c",ch); s输出一个字符串printf("%s","oh my god&…

Go学习第十六章——Gin文件上传与下载

Go web框架——Gin文件上传与下载 1. 文件上传1.1 入门案例(单文件)1.2 服务端保存文件的几种方式SaveUploadedFileCreateCopy 1.3 读取上传的文件1.4 多文件上传 2. 文件下载2.1 快速入门2.2 前后端模式下的文件下载2.3 中文乱码问题 1. 文件上传 1.1 …

年度最佳榜单之 10 大免费数据恢复软件

我们经常会因为不小心从硬盘驱动器、SD 卡和数码相机等存储设备中删除重要数据而丢失它们。还有许多其他原因,如格式化、病毒攻击和不当操作都可能导致数据丢失。在本文中,我向您推荐年度最佳数据恢复软件列表,以帮助恢复丢失的数据。 10 大免…

强大易于编辑的流程图组织图绘制工具draw.io Mac苹果中文版

draw.io可以绘制多种类型的图表,包括但不限于流程图、组织结构图、网络图、UML图、电气工程图等。draw.io提供了丰富的图形元素和编辑功能,使用户能够轻松地创建和编辑各种复杂的图表。同时,该软件还支持多种导出格式,方便用户在不…

Openssl数据安全传输平台017:客户端在Linux上的编译与调试

客户端代码在widows上编译,除了protobuf找不到目录,其他的基本没有什么问题。 然后打开虚拟机,项目文件已经在/home/projects目录下了 进入项目文件,对代码进行编译 第一次 // 找不到protobuf g *.cpp *.cc -ljson -lpthread -…