¿Existe un método Lodash o Underscore que pueda encontrar si un objeto tiene solo las claves dadas de ese objeto? Me gustaría una implementación de Lodash o Underscore aunque esto suene trivial usando JS nativo.
Por ejemplo, si mi objeto se parece y suponiendo que hay un método lodash llamado hasOnly
const obj = { name: undefined, age: 15, school: 'Some school' } _.hasOnly(obj,['name','age']) //return false _.hasOnly(obj,['name','age','city']) //return false _.hasOnly(obj,['name','age','school']) //return true
Parece que no pude encontrar una manera en los documentos
Rápido y sucio:
hasOnly = (obj, props) => _.isEqual(_.keys(obj).sort(), props.sort())
La clasificación se realiza porque estamos comparando matrices.
Como alternativa, uno podría convertir props
y _.keys(obj)
en objetos donde props
y _.keys(obj)
son las claves, mientras que el valor es ficticio, siempre el mismo, como 1
. La función para hacerlo podría ser algo como esto:
make1ValuedObj = keys => _.zipObject(keys, Array(keys.length).fill(1))
Entonces uno los pasaría a _.isEqual
sin tener que ordenar nada:
hasOnly = (obj, props) => _.isEqual(make1ValuedObj(_.keys(obj)), make1ValuedObj(props))
La realidad es que tiene que ocurrir una especie de "clasificación" cuando construyes los objetos, por lo que no creo que haya una ventaja real sobre la solución anterior.
La solución nativa será más rápida en casi todos los casos:
const obj = { name: undefined, age: 15, school: 'Some school' } const hasOnly = (obj,props) => { var objProps = Object.keys(obj) return objProps.length == props.length && props.every(p => objProps.includes(p)) } console.log(hasOnly(obj,['name','age'])) //return false console.log(hasOnly(obj,['name','age','city'])) //return false console.log(hasOnly(obj,['name','age','school'])) //return true
Comparar esto con la otra respuesta usando lodash muestra que la solución lodash es un 95% más lenta (en mi máquina)
Puntos de referencia: https://jsbench.me/r9kz2mwr9c/1
Creo que la respuesta de Enlico está bien, pero para completar mencionaré otra opción que no requiere clasificación. Esto se basa en comparar objetos directamente en lugar de comparar matrices de claves.
Tenga en cuenta que el siguiente código asume el guión bajo original. Para Lodash, reemplace _.mapObject
por _.mapValues
.
// replace all properties by true to prevent costly recursion const mask = obj => _.mapObject(obj, _.constant(true)); function hasOnly(obj, keys) { const masked = mask(obj); // compare obj to a trimmed version of itself return _.isEqual(masked, _.pick(masked, keys)); }