从嵌套结构中取值时如何编写兜底逻辑
github总基地 id="示例代码:">示例代码:
let { a = [] } = b || {}; a.map(item => { item.headerTpl = buildHeader(item);});
问题分析:
对a解构时赋予的默认值(空数组),仅当b.a的值为undefined时才会生效,如果b.a的值为null,默认值就无法生效,使得第二行调用map方法的代码直接报错,所以第一行代码兜底并没有做好。
方案1——Lodash.get方法
结论:数值挖取和后续处理统一使用lodash提供的方法,例如_.map()等基本可以避免在业务层充斥过多校验和防御代码,lodash的API语义化也相对清晰,容易理解开发者意图。但如果和ES6原生方法配合的话,还需要继续做容错处理以免被null坑。
• 路径中有null或undefined时,即使有后续取值路径,也不会报错,而是返回默认值
• 如果取到的值为null,则返回null(不会触发默认值),所以对于期望类型为数组类型的,下一步如果想调用原生数组方法,仍然需要进行类型容错,如果配合lodash提供的其他方法则不用容错。
API和源码地址:https://lodash.com/docs/4.17.15#get
const get = require('lodash/get');const response = { "data": { "history": [{ "date": "2020-09-11", "eat": 0, "sleep": 0, "total": { "student1": { "eat": 9, "sleep": 0 } } },{ "date": "2020-08-21", "eat": 0, "sleep": 53, "total": { "student1": { "eat": 0, "sleep": 13 }, "student1": { "eat": 0, "sleep": 53 } } }], "test":{ "test_undefined": undefined, "test_null": null } }, "message": "success", "status": 0}//常规取值let result1=get(response,'data.history[1].total.student1','defaultValue');let result2=get(response,'data.history[3].total.student1','defaultValue');let result3 = get(response, 'data.test.test_undefined','defaultValue');let result4 = get(response, 'data.test.test_null','defaultValue');let result5 = get(response, 'data.test.test_undefined.lark','defaultValue');let result6 = get(response, 'data.test.test_null.lark','defaultValue');console.log(result1); // {eat:0, sleep:13}console.log(result2); // defaultValueconsole.log(result3); //defaultValueconsole.log(result4); //nullconsole.log(result5); //defaultValueconsole.log(result6); //defaultValue
方案2——使用babel可选链插件
结论:实现原理和语法都更精简,可以更好地配合ES6原生方法。
• 路径中有null或undefined时,即使有后续取值路径,也不会报错,而是返回默认值
• 最终结果为undefined或null时都返回默认值(和lodash.get的区别)
• MDN中关于可选链的描述
首先配置babel插件:
{ "plugins": [ "@babel/plugin-proposal-nullish-coalescing-operator", "@babel/plugin-proposal-optional-chaining" ]}
在代码中使用可选链:
const response = { "data": { "history": [{ "date": "2020-09-11", "eat": 0, "sleep": 0, "total": { "student1": { "eat": 9, "sleep": 0 } } },{ "date": "2020-08-21", "eat": 0, "sleep": 53, "total": { "student1": { "eat": 0, "sleep": 13 }, "student2": { "eat": 0, "sleep": 53 } } }], "test":{ "test_undefined": undefined, "test_null": null } }, "message": "success", "status": 0}let result1 = response.data?.history[1]?.total?.student1 ?? 'defaultValue';let result2 = response.data?.history[3]?.total?.student1 ?? 'defaultValue';let result3 = response.data?.test?.test_undefined ?? 'defaultValue';let result4 = response.data?.test?.test_null ?? 'defaultValue';let result5 = response.data?.test?.test_undefined?.lark ?? 'defaultValue';let result6 = response.data?.test?.test_null?.lark ?? 'defaultValue';console.log(result1); // {eat:0, sleep:13}console.log(result2); // defaultValueconsole.log(result3); // defaultValueconsole.log(result4); // defaultValueconsole.log(result5); // defaultValueconsole.log(result6); // defaultValue
方案3——利用函数式编程实现get方法
原文可见:如何优雅安全地在深层数据结构中取值
/** * * @param {*} p ['a','b'....] 属性路径 * @param {*} o 待取值对象 * @param {*} d 默认值 defaultValue */const get = (p, o, d) => p.reduce((xs, x) => (xs && xs[x]) ? xs[x] : d, o);
babel可选链的编译结果:
源代码:
const a = { b: { c: { d: null } }};let r = a.b?.c?.d ?? "defaultValue";
编译后:
var _a$b$c$d, _a$b, _a$b$c;const a = { b: { c: { d: null } }};let r = (_a$b$c$d = (_a$b = a.b) === null || _a$b === void 0 ? void 0 : (_a$b$c = _a$b.c) === null || _a$b$c === void 0 ? void 0 : _a$b$c.d) !== null && _a$b$c$d !== void 0 ? _a$b$c$d : "defaultValue";
基本逻辑可以按括号从内往外看,并不复杂,就是每次取属性都对undefined和null进行了容错处理。
原文转载:http://www.shaoqun.com/a/485823.html
bsci:https://www.ikjzd.com/w/2339
活动树:https://www.ikjzd.com/w/1518
netporter:https://www.ikjzd.com/w/2132
从嵌套结构中取值时如何编写兜底逻辑github总基地id="示例代码:">示例代码:let{a=[]}=b||{};a.map(item=>{item.headerTpl=buildHeader(item);});问题分析:对a解构时赋予的默认值(空数组),仅当b.a的值为undefined时才会生效,如果b.a的值为null,默认值就无法生效,使得第二行调用map
6pm:https://www.ikjzd.com/w/317
商标抢注:https://www.ikjzd.com/w/1053
亚马逊黄金日购物意愿降低?电子商务整体搜索量下降84%:https://www.ikjzd.com/home/132109
厦门鳌园怎么样?有什么好玩的?:http://tour.shaoqun.com/a/43057.html
北戴河为什么避暑比较好?:http://tour.shaoqun.com/a/61506.html
No comments:
Post a Comment