先看效果图

在这之前有大佬实现了微信小程序中的eval,亲测过,可行,但体量有点大,决定自己写个简单的eval,不求实现复杂逻辑,够用就行。

一、背景

应公司需求,计算表达式的true,false值,如
"STATUS===10||STATUS===20"

计算之前需将其中的STATUS变量转变为实际的值如:
"10===10||10===20"

为了更好辨认变量,将变量用特殊字符串标记起来,如:[%=STATUS%]
将原表达式定为"[%=STATUS%]===10||[%=STATUS%]===20"

二、实现逻辑

将给定表达式"[%=STATUS%]===10||[%=STATUS%]===20"分解成数组,同时将标记的变量STATUS赋值并去掉标记字符串,得到的字符串如下:
(假设实际STATUS==='10'
['10', '===', '10', '||', '10', '===', '20']
根据数组中的||&&拆分成两个简单的数组['10', '===', '10']'10', '===', '20']
分别硬判断得到两个boolean值,再将两个boolean值做||&&操作,得到最终的boolean。
当然这里是两个小表达式组成的情况,如果是三个或以上的情况,就要用到循环算法来解决,这里我采用递归算法。

三、贴上代码

封装类utils.js

const sfEval = (model, str, property = null) => {let cs = str.replace(/\s*/g, '').replace(/\[%=/g, '').replace(/%\]/g, '').split(/(&&|\|\||>|<|===|!==|>=|<=|\(|\))/)for (const cIdx in cs) {if (property && model[cs[cIdx]] !== undefined) {// 处理0.aaa的问题// 处理以0开头的字符串// parseFloat// parseFloat('') NaN// parseFloat(null) NaN// parseFloat(true) NaN// parseFloat(false) NaN// Number('0.aaa') NAN// 不是''不是null不是true不是false// 是false // 后面即使是true也不走// 是 0.aaa true // 后面是false// 对象和数组都是parseFloat之后都是NaNif (model[cs[cIdx]]) {if (!isNaN(parseFloat(model[cs[cIdx]][property])) && !isNaN(Number(model[cs[cIdx]][property]))) {// 之后一个判断处理字符串'0000'的情况// 如何处理if ((model[cs[cIdx]][property] + '').charAt() === '0' && (model[cs[cIdx]][property] + '').length > 1) {cs[cIdx] = "'" + model[cs[cIdx]][property] + "'"} else {cs[cIdx] = parseFloat(model[cs[cIdx]][property])}} else {// 处理下拉框的清除问题 null以及其他null的问题if (model[cs[cIdx]][property] === null) {model[cs[cIdx]][property] = ''}cs[cIdx] = "'" + model[cs[cIdx]][property] + "'"}}} else if (model[cs[cIdx]] !== undefined) {// 处理0.aaa的问题// 处理以0开头的字符串// parseFloat// parseFloat('') NaN// parseFloat(null) NaN// parseFloat(true) NaN// parseFloat(false) NaN// Number('0.aaa') NAN// 不是''不是null不是true不是false// 是false // 后面即使是true也不走// 是 0.aaa true // 后面是false// 对象和数组都是parseFloat之后都是NaNif (!isNaN(parseFloat(model[cs[cIdx]])) && !isNaN(Number(model[cs[cIdx]]))) {// 之后一个判断处理字符串'0000'的情况// 如何处理if ((model[cs[cIdx]] + '').charAt() === '0' && (model[cs[cIdx]] + '').length > 1) {cs[cIdx] = "'" + model[cs[cIdx]] + "'"} else {cs[cIdx] = parseFloat(model[cs[cIdx]])}} else {// 处理下拉框的清除问题 null以及其他null的问题if (model[cs[cIdx]] === null) {model[cs[cIdx]] = ''}cs[cIdx] = "'" + model[cs[cIdx]] + "'"}} else if ((cs[cIdx].indexOf("'") < 0 || (!isNaN(parseFloat(cs[cIdx].replace(/'/g, ''))) && !isNaN(Number(cs[cIdx].replace(/'/g, ''))))) && !cs[cIdx].match(/^(&&|\|\||>|<|===|!==|>=|<=|\(|\))$/)) {// convert to string fix bug for model is null with FIELD = '0', FIELD is undefinedif (!isNaN(parseFloat(cs[cIdx].replace(/'/g, ''))) && !isNaN(Number(cs[cIdx].replace(/'/g, '')))) {if ((cs[cIdx] + '').charAt() === '0' && (cs[cIdx] + '').length > 1) {cs[cIdx] = "'" + cs[cIdx] + "'"} else {cs[cIdx] = parseFloat(cs[cIdx].replace(/'/g, ''))}} else {cs[cIdx] = "'" + cs[cIdx] + "'"}}}let csTemp = JSON.parse(JSON.stringify(cs))return true && fn(csTemp)
}const fn = (csTemp) => {let resultBool = falselet arr1 = []let arr2 = []if (csTemp.length < 4) {resultBool = calcFuc(csTemp)return resultBool} else {for (let i in csTemp) {if (csTemp[i] == '&&' || csTemp[i] == '||') {arr1 = csTemp.slice(0, i)arr2 = csTemp.slice(Number(i) + 1, Number(i) + 4)if (csTemp[i] == '&&') {resultBool = calcFuc(arr1) && calcFuc(arr2)} else {resultBool = calcFuc(arr1) || calcFuc(arr2)}csTemp.splice(0, Number(i) + 4, resultBool)return fn(csTemp)break}}}
}const calcFuc = (arr) => {for (let i = 0; i < arr.length; i++) {switch (arr[i]) {case '&&':return arr[i - 1] && arr[i + 1]case '||':return arr[i - 1] || arr[i + 1]case '>':return arr[i - 1] > arr[i + 1]case '<':return arr[i - 1] < arr[i + 1]case '===':return arr[i - 1] === arr[i + 1]case '!==':return arr[i - 1] !== arr[i + 1]case '>=':return arr[i - 1] >= arr[i + 1]case '<=':return arr[i - 1] <= arr[i + 1]case true:return truedefault:break}}return false
}module.exports = {sfEval
}

四、调用方法

先import封装方法,然后调用

let model = {USER: 'a',STATUS: 0,ROLE: 2}
let str = "[%=STATUS%]==='0'&&[%=ROLE%]==='2'&&[%=USER%]==='a'"
console.log('sfEval', sfEval(model, str))

五、运行结果

六、注意事项

本篇文章实现逻辑中包含的eval可仅跑通类似以下形式的字符串:

"2===2&&3!==4"
"2===2&&3!==4&&'a'!=='b'"
"2===2&&3!==4&&'a'!=='b'||'a'!=='b'"
"2===2||3!==4&&'a'!=='b'||'a'!=='b'"

不支持括号,按照从左到右的顺序计算。

七、结束语

到此就结束了,希望能帮到各位,记得拿走时请扣6
有问题在评论区留言

微信小程序实现带参数的字符串表达式判断真值相关推荐

  1. 微信小程序中带参数返回上一页的方法总结(三种)

    本篇文章给大家带来的内容是关于微信小程序中带参数返回上一页的方法总结(三种),有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助. 方法一 把当前页面数据放入本地缓存( wx.setStor ...

  2. 微信小程序路径带参数跳转

    微信小程序路径带参数跳转 release_con: function () {console.log(this.data.cateid)wx.navigateTo({url: '/pages/rele ...

  3. 微信小程序分享带参数

    方法如下 Page({onShareAppMessage: function (res) {return {title: '转发标题',path: '/page/index?name=liuliang ...

  4. 小程序提交表单mysql_GitHub - kun19911227/minipro: 微信小程序提交带图片的表单

    minipro 微信小程序提交带图片的表单 目录说明 upload_images ├── pages │ ├── upload_info 提交表单 │ └── display_info 信息展示 ├─ ...

  5. uniapp App跳转微信小程序并互相传递参数、接收微信小程序传递的参数

    本文是uniapp打包成安卓App. 一.注意事项 1.用到了分享功能,在打包App时,需要配置manifest.json:App 模块配置->Share.按照提示填写微信分享的信息,appid ...

  6. 微信小程序轮播图中间变大_微信小程序实现带放大效果的轮播图

    本文实例为大家分享了微信小程序实现带放大效果的轮播图,供大家参考,具体内容如下 效果如图 WXML WXSS .Carousel{ margin-top: 49px; background-color ...

  7. 微信小程序获取带表情的微信名乱码问题

    微信小程序获取带表情的微信名乱码问题 在后台获取完微信用户数据后,对微信名进行UTF-8编码 URLEncoder.encode(nickName, "utf-8") ,将编码后的 ...

  8. 微信小程序组件 —— 带搜索功能的选择器

    微信小程序组件 -- 带搜索功能的选择器 效果 组件 search-picker 文件 wxml 文件: <view class="search-picker">< ...

  9. 微信小程序设置对象参数

    顺带一提:微信小程序是不能直接连接数据库的,所以想要获取数据库的真实地址是要通过访问接口来实现的. 1.微信小程序设置普通参数: data: {abc: "",qwe: " ...

最新文章

  1. 如何起一个好的学术期刊论文题目?
  2. 有关接口和抽象类的问题
  3. 永远的Macromedia, Macromedia Forever
  4. 骗子防不胜防,我们该如何安全上网?
  5. 3 CSS 高级语法
  6. VLAN访问控制列表(VACL)的配置方法
  7. 解决8080端口被占用问题
  8. 马尔科夫模型 Markov Model
  9. 网络工程师考试-计算机网络笔记
  10. 数据库原理与应用——课程介绍及数据库系统概论(上)
  11. LRC歌词原理和实现高仿Android网易云音乐
  12. D3.js学习指北--第二章,基础复习
  13. CSDN的Markdown编辑器中等比例缩放图片的方法
  14. eclipse开发jsp网站
  15. 渗透工具之hackbar 安装
  16. 硬件设计之元件:电阻
  17. [10]ESP32+气压计MS5611移植与调试
  18. 浏览器高度 document.body.scrollTop用法
  19. 服务器安装信任描述文件,OS X Server:在使用 TLS、TTLS 或 PEAP 时如何在“配置描述文件”中配置 RADIUS 服务器信任...
  20. eplan怎样创建和修改图框_在EPLAN中怎么将别人的图框导出,然后自己修改

热门文章

  1. calc()函数及vmin,vmax,vh,vw的认识,在family里的实战运用
  2. 到期域名查询 查询域名到期时间的网站
  3. IDEA 2019 图文教程: 从入门到上瘾教程
  4. 贪婪算法小结(Java版)
  5. 原型和原型链,原型继承和原型链继承
  6. Java语言十五讲(第十二讲 Multi-Thread多线程12.2)
  7. python: 找到dataframe某列中含有特定字段字符串的行 遍历dataframe 函数返回为空 找到特定单元格
  8. java的转义字符 day3
  9. 用Python调用CMD命令 批量转换Webp到Png
  10. 逼狼去吃草,太经典了!(我看了10遍)