对于对象的属性存在性检测一直是我们判断条件几乎每天遇到的,但是你是否又在具有‘坏味道’ 代码很绝望,现在我们提供几种处理‘坏味道’ 对象链式取值方式
例子:
const props = {
a: {
b: [
{ c: 'fe', d: [ 'hello', 'laodao' ] },
{ c: 'fe', d: [ 'hello' ] },
{ c: 'fe', d: []}
],
d: [...]
}
}
props.a &&
props.a.b &&
props.a.b[0] &&
props.a.b[0].d
想到这种方法主要是还是之前有compose以及pipe这种函数,如果没有了解过函数式编程的人,可以参考我之前写的函数式编程教程,
const get = (p, o) => p.reduce((xs, x) => (xs && xs[x]) ? xs[x] : null, o)
console.log(get(['a', 'b', 0, 'd'], props)) // [ 'hello', 'laodao' ]
console.log(get(['a', 'bs', 0, 'd'], props)) // null
关于此表达式的参数p代表就是get第一参数数组,o为props,当第一次时候xs为props,x为’a‘,如果xs && xs[x]都存在那么结果就为xs[x]即 a,那么a就会赋值给o,此时的o就为a,由此可以看来reduce非常适合对于数组和对象之间转换的场景,可以定制更多细节,例如:
let names = ['Alice', 'Bob', 'Tiff', 'Bruce', 'Alice'];
let nameNum = names.reduce((pre,cur)=>{
if(cur in pre){
pre[cur]++
}else{
pre[cur] = 1
}
return pre
},{})
console.log(nameNum); //{Alice: 2, Bob: 1, Tiff: 1, Bruce: 1}
想到这个方法因为proxy对obj的代理,可以定制get函数以及set函数,可以对获取以及设置进行更加详细的设置
function pointer(obj, path = []) {
return new Proxy(() => {}, {
get (target, property) {
return pointer(obj, path.concat(property))
},
apply (target, self, args) {
let val = obj;
let parent;
for(let i = 0; i < path.length; i++) {
if(val === null || val === undefined) break;
parent = val;
val = val[path[i]]
}
if(val === null || val === undefined) {
val = args[0]
}
return val;
}
})
}
let c = {a: {b: [1, ,2 ,3]}}
pointer(props).a(); // {b:[],d:[]}
pointer(props).a.b(); // [,,,]
pointer(props).a.b.d('default value'); // default value
可以使用Ramda 函数式类库完成
const get = R.path(['a', 'b', 0, 'd'])
get(props) // [ 'hello', 'laodao' ]
get({}) // null
Maybe 是函数式编程中的一个概念,是一种常用的函子(functor),通常用来处理函数式编程中可能存在的空值问题。
Maybe 原始参考用法,很传统:
// MayBe 函数定义
const MayBe = function (val) {
this.value = val;
}
MayBe.of = function (val) {
return new MayBe(val);
}
// MayBe map 函数定义
MayBe.prototype.isNothing = function () {
return (this.value === null || this.value === underfind)
}
MayBe.prototype.map = function (fn) {
return this.isNothing() ? MayBe.of(null) : MayBe.of(fn(this.value));
}
Maybe结果不确定,即可能是Just(value),又可能是Nothing,所以我们一般使用getOrElse来对异常处理,这样我们就可以去除具有 '坏味道' 的防御型代码:folktale/maybe
const Maybe = require('folktale/maybe')
const foo = Maybe.fromNullable(Math.random() >= 0.5 ? 'bar' : undefined)
//=> 50%概率为 Maybe.Just('bar'),50%概率为 Maybe.Nothing()
const unsafe_result = foo.get()
// 有50%的概率会报错:
// TypeError: Can't extract the value of a Nothing.
// 为了安全起见,我们使用 getOrElse()
const result = foo.getOrElse('nothing!!!')
// 50%:'bar',50%:'nothing!!!'
实际应用:
const Maybe = require('folktale/maybe')
const list = [{ name: 'tom', age: 18 }]
// 坏味道的防御式代码
const person = list.find(person => person.name === 'stark')
let ageText = 'No Age'
if (person && person.age !== undefined) {
ageText = `User Age: ${person.age}`
}
// Maybe
const ageText = Maybe.fromNullable(
list.find(person => person.name === 'stark')
)
.map(person => `User Age: ${person.age}`)
.getOrElse('No Age')
使用maybe实现get函数
const Maybe = require('folktale/maybe')
function get(object, ...keys) {
if (keys.length === 0) {
return Maybe.Just(object)
} else if (object[keys[0]]) {
return get(object[keys[0]], ...keys.slice(1))
} else {
return Maybe.Nothing()
}
}
const foo = { a: { b: { c: { d: 42 } } } }
const bar = {}
get(foo 'a', 'b', 'c', 'd').getOrElse(0)
//=> 42
get(bar 'a', 'b', 'c', 'd').getOrElse(0)
//=> 0
------------------------------------
const data = await fetchData()
const firstUserName = get(data, 'list', 0, 'name').getOrElse('no user found')
-------对比
const data = await fetchData()
let firstUserName = 'no user found'
if (data && data.list && data.list.length > 0 && data.list[0].name !== undefined) {
firstUserName = data.list[0].name
}
var object = { a: [{ b: { c: 3 } }] };
var result = _.get(object, 'a[0].b.c', 1);
console.log(result);
// output: 3
--------------------------------------
function get (obj, props, def) {
if((obj == null) || obj == null || typeof props !== 'string') return def;
const temp = props.split('.');
const fieldArr = [].concat(temp);
temp.forEach((e, i) => {
if(/^(\w+)\[(\w+)\]$/.test(e)) {
const matchs = e.match(/^(\w+)\[(\w+)\]$/);
const field1 = matchs[1];
const field2 = matchs[2];
const index = fieldArr.indexOf(e);
fieldArr.splice(index, 1, field1, field2);
}
})
return fieldArr.reduce((pre, cur) => {
const target = pre[cur] || def;
if(target instanceof Array) {
return [].concat(target);
}
if(target instanceof Object) {
return Object.assign({}, target)
}
return target;
}, obj)
}
var c = {a: {b : [1,2,3] }}
get(c ,'a.b') // [1,2,3]
get(c, 'a.b[1]') // 2
get(c, 'a.d', 12) // 12
解构赋值语法是一种 Javascript 表达式。通过解构赋值, 可以将属性/值从对象/数组中取出,赋值给其他变量。
const c = {a:{b: 3}}
const { a: result } = c;// result : {b: 3}
const {a: { c: result = 4 }} = c;// result: 4
javascript方法的链式调用,使用它能让代码很简洁,易懂,而且最大的好处就是避免多次重复使用一个对象变量。 包括工厂模式的写法,Promise异步链式 等做说明。
这篇文章主要介绍了PHP实现链式操作的三种方法,结合实例形式分析了php链式操作的相关实现技巧与使用注意事项,需要的朋友可以参考下,本文实例讲述了PHP实现链式操作的三种方法。分享给大家供大家参考,具体如下:
熟悉Jquery的同学都知道,它对dom的操作基本都链式调用的写法,这种给人感觉就是很简洁,易懂,而且最大的好处就是避免多次重复使用一个对象变量。链式操作是在对象的方法中通过最后返回自身对象(return this),返回的对象就可以继续调用它里面的方法
then方法里接受两个函数作为参数,分别是resolve和reject后执行的回调,他返回的是一个新的Promise实例(不是原来那个Promise实例)。return 值的情况(无return的情况下就返回undefined,也是返回值)
链式调用原理就是作用域链;实现需要做的工作;对象方法的处理 (操作方法),处理完成返回对象的引用(操作对象),第2步链式实现的方式:
内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!