objetos - Prueba de existencia de clave de objeto JavaScript anidada
object.keys map (30)
Actualizar
Parece que lodash ha agregado _.get
para todas las necesidades de sus propiedades anidadas.
_.get(countries, ''greece.sparta.playwright'')
Respuesta anterior
lodash usuarios de lodash pueden disfrutar de lodash.contrib que tiene un par de métodos que mitigan este problema .
getPath
Firma: _.getPath(obj:Object, ks:String|Array)
Obtiene el valor a cualquier profundidad en un objeto anidado basado en la ruta descrita por las claves dadas. Las claves pueden darse como una matriz o como una cadena separada por puntos. Devuelve undefined
si no se puede llegar a la ruta.
var countries = {
greece: {
athens: {
playwright: "Sophocles"
}
}
}
};
_.getPath(countries, "greece.athens.playwright");
// => "Sophocles"
_.getPath(countries, "greece.sparta.playwright");
// => undefined
_.getPath(countries, ["greece", "athens", "playwright"]);
// => "Sophocles"
_.getPath(countries, ["greece", "sparta", "playwright"]);
// => undefined
Si tengo una referencia a un objeto:
var test = {};
que potencialmente (pero no inmediatamente) tendrá objetos anidados, algo como:
{level1: {level2: {level3: "level3"}}};
¿Cuál es la mejor manera de probar la existencia de claves en los objetos más profundamente anidados?
alert(test.level1);
produce undefined
, pero alert(test.level1.level2.level3);
falla
Actualmente estoy haciendo algo como esto:
if(test.level1 && test.level1.level2 && test.level1.level2.level3) {
alert(test.level1.level2.level3);
}
Pero me preguntaba si hay una mejor manera.
ES6 respuesta, probado a fondo :)
const propExists = (obj, path) => {
return !!path.split(''.'').reduce((obj, prop) => {
return obj && obj[prop] ? obj[prop] : undefined;
}, obj)
}
→ ver Codepen con cobertura de prueba completa
Ahora también podemos usar reduce
para recorrer las claves anidadas:
// @params o<object>
// @params path<string> expects ''obj.prop1.prop2.prop3''
// returns: obj[path] value or ''false'' if prop doesn''t exist
const objPropIfExists = o => path => {
const levels = path.split(''.'');
const res = (levels.length > 0)
? levels.reduce((a, c) => a[c] || 0, o)
: o[path];
return (!!res) ? res : false
}
const obj = {
name: ''Name'',
sys: { country: ''AU'' },
main: { temp: ''34'', temp_min: ''13'' },
visibility: ''35%''
}
const exists = objPropIfExists(obj)(''main.temp'')
const doesntExist = objPropIfExists(obj)(''main.temp.foo.bar.baz'')
console.log(exists, doesntExist)
Aquí hay un patrón que recogí de Oliver Steele :
var level3 = (((test || {}).level1 || {}).level2 || {}).level3;
alert( level3 );
De hecho, todo el artículo es una discusión de cómo puedes hacer esto en javascript. Se decide a usar la sintaxis anterior (que no es tan difícil de leer una vez que te acostumbras) como un idioma.
Basado en un comentario anterior , aquí hay otra versión en la que el objeto principal tampoco se pudo definir:
// Supposing that our property is at first.second.third.property:
var property = (((typeof first !== ''undefined'' ? first : {}).second || {}).third || {}).property;
Creo que esto es una ligera mejora (se convierte en un 1-liner):
alert( test.level1 && test.level1.level2 && test.level1.level2.level3 )
Esto funciona porque el operador && devuelve el operando final que evaluó (y cortocircuita).
Creo que la siguiente secuencia de comandos da una representación más legible.
declarar una función:
var o = function(obj) { return obj || {};};
entonces úsalo así:
if (o(o(o(o(test).level1).level2).level3)
{
}
Lo llamo "técnica de payaso triste" porque está usando la señal o (
EDITAR:
Aquí hay una versión para TypeScript.
da verificaciones de tipos en tiempo de compilación (así como también el intellisense si usa una herramienta como Visual Studio)
export function o<T>(someObject: T, defaultValue: T = {} as T) : T {
if (typeof someObject === ''undefined'' || someObject === null)
return defaultValue;
else
return someObject;
}
El uso es el mismo:
o(o(o(o(test).level1).level2).level3
¡Pero esta vez el intellisense funciona!
Además, puede establecer un valor predeterminado:
o(o(o(o(o(test).level1).level2).level3, "none")
Debe hacerlo paso a paso si no desea un TypeError
, porque si uno de los miembros es null
o undefined
está undefined
, e intenta acceder a un miembro, se lanzará una excepción.
Puede simplemente catch
la excepción o hacer una función para probar la existencia de múltiples niveles, algo como esto:
function checkNested(obj /*, level1, level2, ... levelN*/) {
var args = Array.prototype.slice.call(arguments, 1);
for (var i = 0; i < args.length; i++) {
if (!obj || !obj.hasOwnProperty(args[i])) {
return false;
}
obj = obj[args[i]];
}
return true;
}
var test = {level1:{level2:{level3:''level3''}} };
checkNested(test, ''level1'', ''level2'', ''level3''); // true
checkNested(test, ''level1'', ''level2'', ''foo''); // false
Escribí mi propia función que toma la ruta deseada y tiene una función de devolución de llamada buena y mala.
function checkForPathInObject(object, path, callbackGood, callbackBad){
var pathParts = path.split(".");
var currentObjectPath = object;
// Test every step to see if it exists in object
for(var i=0; i<(pathParts.length); i++){
var currentPathPart = pathParts[i];
if(!currentObjectPath.hasOwnProperty(pathParts[i])){
if(callbackBad){
callbackBad();
}
return false;
} else {
currentObjectPath = currentObjectPath[pathParts[i]];
}
}
// call full path in callback
callbackGood();
}
Uso:
var testObject = {
level1:{
level2:{
level3:{
}
}
}
};
checkForPathInObject(testObject, "level1.level2.level3", function(){alert("good!")}, function(){alert("bad!")}); // good
checkForPathInObject(testObject, "level1.level2.level3.levelNotThere", function(){alert("good!")}, function(){alert("bad!")}); //bad
Esta es mi opinión: la mayoría de estas soluciones ignoran el caso de una matriz anidada como en:
obj = {
"l1":"something",
"l2":[{k:0},{k:1}],
"l3":{
"subL":"hello"
}
}
Es posible que desee comprobar obj.l2[0].k
Con la siguiente función, puede hacer deeptest(''l2[0].k'',obj)
La función devolverá verdadero si el objeto existe, falso de lo contrario
function deeptest(keyPath, testObj) {
var obj;
keyPath = keyPath.split(''.'')
var cKey = keyPath.shift();
function get(pObj, pKey) {
var bracketStart, bracketEnd, o;
bracketStart = pKey.indexOf("[");
if (bracketStart > -1) { //check for nested arrays
bracketEnd = pKey.indexOf("]");
var arrIndex = pKey.substr(bracketStart + 1, bracketEnd - bracketStart - 1);
pKey = pKey.substr(0, bracketStart);
var n = pObj[pKey];
o = n? n[arrIndex] : undefined;
} else {
o = pObj[pKey];
}
return o;
}
obj = get(testObj, cKey);
while (obj && keyPath.length) {
obj = get(obj, keyPath.shift());
}
return typeof(obj) !== ''undefined'';
}
var obj = {
"l1":"level1",
"arr1":[
{"k":0},
{"k":1},
{"k":2}
],
"sub": {
"a":"letter A",
"b":"letter B"
}
};
console.log("l1: " + deeptest("l1",obj));
console.log("arr1[0]: " + deeptest("arr1[0]",obj));
console.log("arr1[1].k: " + deeptest("arr1[1].k",obj));
console.log("arr1[1].j: " + deeptest("arr1[1].j",obj));
console.log("arr1[3]: " + deeptest("arr1[3]",obj));
console.log("arr2: " + deeptest("arr2",obj));
Estaba buscando el valor que se devolvería si la propiedad existe, así que modifiqué la respuesta de CMS anterior. Esto es lo que se me ocurrió:
function getNestedProperty(obj, key) {
// Get property array from key string
var properties = key.split(".");
// Iterate through properties, returning undefined if object is null or property doesn''t exist
for (var i = 0; i < properties.length; i++) {
if (!obj || !obj.hasOwnProperty(properties[i])) {
return;
}
obj = obj[properties[i]];
}
// Nested property found, so return the value
return obj;
}
Usage:
getNestedProperty(test, "level1.level2.level3") // "level3"
getNestedProperty(test, "level1.level2.foo") // undefined
Hay una función aquí en el código de código (safeRead) que hará esto de manera segura ... es decir,
safeRead(test, ''level1'', ''level2'', ''level3'');
si alguna propiedad es nula o no definida, se devuelve una cadena vacía
He realizado pruebas de rendimiento (gracias a cdMinix por agregar lodash) en algunas de las sugerencias propuestas a esta pregunta con los resultados que se enumeran a continuación.
Descargo de responsabilidad # 1 Convertir cadenas en referencias es una meta-programación innecesaria y probablemente sea mejor evitarla. No pierdas de vista tus referencias para empezar. Lea más de esta respuesta a una pregunta similar .
Renuncia # 2 Estamos hablando de millones de operaciones por milisegundo aquí. Es muy poco probable que alguno de estos haga mucha diferencia en la mayoría de los casos de uso. Elija lo que tenga más sentido sabiendo las limitaciones de cada uno. Para mi iría con algo como
reduce
por conveniencia.
Envoltura de objetos (por Oliver Steele) - 34% - más rápido
var r1 = (((test || {}).level1 || {}).level2 || {}).level3;
var r2 = (((test || {}).level1 || {}).level2 || {}).foo;
Solución original (sugerida en la pregunta) - 45%
var r1 = test.level1 && test.level1.level2 && test.level1.level2.level3;
var r2 = test.level1 && test.level1.level2 && test.level1.level2.foo;
checkNested - 50%
function checkNested(obj) {
for (var i = 1; i < arguments.length; i++) {
if (!obj.hasOwnProperty(arguments[i])) {
return false;
}
obj = obj[arguments[i]];
}
return true;
}
get_if_exist - 52%
function get_if_exist(str) {
try { return eval(str) }
catch(e) { return undefined }
}
validChain - 54%
function validChain( object, ...keys ) {
return keys.reduce( ( a, b ) => ( a || { } )[ b ], object ) !== undefined;
}
objHasKeys - 63%
function objHasKeys(obj, keys) {
var next = keys.shift();
return obj[next] && (! keys.length || objHasKeys(obj[next], keys));
}
nestedPropertyExists - 69%
function nestedPropertyExists(obj, props) {
var prop = props.shift();
return prop === undefined ? true : obj.hasOwnProperty(prop) ? nestedPropertyExists(obj[prop], props) : false;
}
_.get - 72%
deeptest - 86%
function deeptest(target, s){
s= s.split(''.'')
var obj= target[s.shift()];
while(obj && s.length) obj= obj[s.shift()];
return obj;
}
Payasos tristes - 100% - mas lento
var o = function(obj) { return obj || {} };
var r1 = o(o(o(o(test).level1).level2).level3);
var r2 = o(o(o(o(test).level1).level2).foo);
Intenté un enfoque recursivo:
function objHasKeys(obj, keys) {
var next = keys.shift();
return obj[next] && (! keys.length || objHasKeys(obj[next], keys));
}
El ! keys.length ||
arranca de la recursión para que no ejecute la función sin teclas para probar. Pruebas:
obj = {
path: {
to: {
the: {
goodKey: "hello"
}
}
}
}
console.log(objHasKeys(obj, [''path'', ''to'', ''the'', ''goodKey''])); // true
console.log(objHasKeys(obj, [''path'', ''to'', ''the'', ''badKey''])); // undefined
Lo estoy usando para imprimir una vista html amigable de un montón de objetos con claves / valores desconocidos, por ejemplo:
var biosName = objHasKeys(myObj, ''MachineInfo:BiosInfo:Name''.split('':''))
? myObj.MachineInfo.BiosInfo.Name
: ''unknown'';
La respuesta dada por CMS funciona bien con la siguiente modificación para las comprobaciones nulas también
function checkNested(obj /*, level1, level2, ... levelN*/)
{
var args = Array.prototype.slice.call(arguments),
obj = args.shift();
for (var i = 0; i < args.length; i++)
{
if (obj == null || !obj.hasOwnProperty(args[i]) )
{
return false;
}
obj = obj[args[i]];
}
return true;
}
Las siguientes opciones fueron elaboradas a partir de esta respuesta . El mismo árbol para ambos:
var o = { a: { b: { c: 1 } } };
Deja de buscar cuando no está definido
var u = undefined;
o.a ? o.a.b ? o.a.b.c : u : u // 1
o.x ? o.x.y ? o.x.y.z : u : u // undefined
(o = o.a) ? (o = o.b) ? o.c : u : u // 1
Asegura cada nivel uno por uno
var $ = function (empty) {
return function (node) {
return node || empty;
};
}({});
$($(o.a).b).c // 1
$($(o.x).y).z // undefined
No vi ningún ejemplo de alguien que usa Proxies
Así que se me ocurrió la mía. Lo mejor de esto es que no tienes que interpolar cadenas. Realmente puedes devolver una función de objeto capaz de encadenar y hacer algunas cosas mágicas con ella. Incluso puede llamar a funciones y obtener índices de matriz para verificar objetos profundos
function resolve(target) {
var noop = () => {} // We us a noop function so we can call methods also
return new Proxy(noop, {
get(noop, key) {
// return end result if key is _result
return key === ''_result''
? target
: resolve( // resolve with target value or undefined
target === undefined ? undefined : target[key]
)
},
// if we want to test a function then we can do so alos thanks to using noop
// instead of using target in our proxy
apply(noop, that, args) {
return resolve(typeof target === ''function'' ? target.apply(that, args) : undefined)
},
})
}
// some modified examples from the accepted answer
var test = {level1: {level2:() => ({level3:''level3''})}}
var test1 = {key1: {key2: [''item0'']}}
// You need to get _result in the end to get the final result
console.log(resolve(test).level1.level2().level3._result)
console.log(resolve(test).level1.level2().level3.level4.level5._result)
console.log(resolve(test1).key1.key2[0]._result)
console.log(resolve(test1)[0].key._result) // don''t exist
El código anterior funciona bien para cosas síncronas. Pero, ¿cómo probaría algo que es asíncrono como esta llamada ajax? ¿Cómo se prueba eso? ¿qué pasa si la respuesta no es json cuando devuelve un error de 500 http?
window.fetch(''https://httpbin.org/get'')
.then(function(response) {
return response.json()
})
.then(function(json) {
console.log(json.headers[''User-Agent''])
})
seguro que podría usar async / await para deshacerse de algunas devoluciones de llamada. Pero ¿y si pudieras hacerlo aún más mágicamente? algo que se parece a esto:
fetch(''https://httpbin.org/get'').json().headers[''User-Agent'']
Probablemente te preguntes dónde están todas las promesas y .then
cadenas ... esto podría estar bloqueando todo lo que sabes ... pero al usar la misma técnica de Proxy con la promesa, puedes probar un camino complejo profundamente anidado para su existencia sin tener que escribir un función única
function resolve(target) {
return new Proxy(() => {}, {
get(noop, key) {
return key === ''then'' ? target.then.bind(target) : resolve(
Promise.resolve(target).then(target => {
if (typeof target[key] === ''function'') return target[key].bind(target)
return target[key]
})
)
},
apply(noop, that, args) {
return resolve(target.then(result => {
return result.apply(that, args)
}))
},
})
}
// this feels very much synchronous but are still non blocking :)
resolve(window) // this will chain a noop function until you call then()
.fetch(''https://httpbin.org/get'')
.json()
.headers[''User-Agent'']
.then(console.log, console.warn) // you get a warning if it doesn''t exist
// You could use this method also for the first test object
// also, but it would have to call .then() in the end
// Another example
resolve(window)
.fetch(''https://httpbin.org/get?items=4&items=2'')
.json()
.args
.items
// nice that you can map an array item without even having it ready
.map(n => ~~n * 4)
.then(console.log, console.warn) // you get a warning if it doesn''t exist
Pensé que agregaría otro que se me ocurrió hoy. La razón por la que me siento orgulloso de esta solución es que evita los soportes anidados que se utilizan en muchas soluciones como Object Wrap (por Oliver Steele) :
(en este ejemplo, uso un guión bajo como una variable de marcador de posición, pero cualquier nombre de variable funcionará)
//the ''test'' object
var test = {level1: {level2: {level3: ''level3''}}};
let _ = test;
if ((_=_.level1) && (_=_.level2) && (_=_.level3)) {
let level3 = _;
//do stuff with level3
}
//you could also use ''stacked'' if statements. This helps if your object goes very deep.
//(formatted without nesting or curly braces except the last one)
let _ = test;
if (_=_.level1)
if (_=_.level2)
if (_=_.level3) {
let level3 = _;
//do stuff with level3
}
//or you can indent:
if (_=_.level1)
if (_=_.level2)
if (_=_.level3) {
let level3 = _;
//do stuff with level3
}
Puede leer una propiedad de objeto a cualquier profundidad, si maneja el nombre como una cadena: ''t.level1.level2.level3''
.
window.t={level1:{level2:{level3: ''level3''}}};
function deeptest(s){
s= s.split(''.'')
var obj= window[s.shift()];
while(obj && s.length) obj= obj[s.shift()];
return obj;
}
alert(deeptest(''t.level1.level2.level3'') || ''Undefined'');
Devuelve undefined
si alguno de los segmentos undefined
está undefined
.
Sé que esta pregunta es antigua, pero quería ofrecer una extensión agregando esto a todos los objetos. Sé que la gente tiende a fruncir el ceño al usar el prototipo de Objeto para la funcionalidad extendida de objetos, pero no encuentro nada más fácil que hacer esto. Además, ahora se permite con el método Object.defineProperty .
Object.defineProperty( Object.prototype, "has", { value: function( needle ) {
var obj = this;
var needles = needle.split( "." );
for( var i = 0; i<needles.length; i++ ) {
if( !obj.hasOwnProperty(needles[i])) {
return false;
}
obj = obj[needles[i]];
}
return true;
}});
Ahora, para probar cualquier propiedad en cualquier objeto, simplemente puede hacer:
if( obj.has("some.deep.nested.object.somewhere") )
Aquí hay un jsfiddle para probarlo, y en particular incluye algunos jQuery que se rompen si modifica el Object.prototype directamente debido a que la propiedad se vuelve enumerable. Esto debería funcionar bien con bibliotecas de terceros.
Sobre la base de esta respuesta , se me ocurrió esta función genérica utilizando ES2015
que resolvería el problema
function validChain( object, ...keys ) {
return keys.reduce( ( a, b ) => ( a || { } )[ b ], object ) !== undefined;
}
var test = {
first: {
second: {
third: "This is not the key your are looking for"
}
}
}
if ( validChain( test, "first", "second", "third" ) ) {
console.log( test.first.second.third );
}
También puede usar la propuesta de encadenamiento opcional tc39 junto con babel 7 - tc39-proposal-optional-chaining
El código se vería así:
const test = test?.level1?.level2?.level3;
if (test) alert(test);
Una forma simple es esta:
try {
alert(test.level1.level2.level3);
} catch(e) {
alert("undefined"); // this is optional to put any output here
}
El try/catch
captura los casos en los que no se ha definido ninguno de los objetos de nivel superior, como test, test.level1, test.level1.level2.
Una versión más corta, ES5 de la excelente respuesta de @ CMS:
// Check the obj has the keys in the order mentioned. Used for checking JSON results.
var checkObjHasKeys = function(obj, keys) {
var success = true;
keys.forEach( function(key) {
if ( ! obj.hasOwnProperty(key)) {
success = false;
}
obj = obj[key];
})
return success;
}
Con una prueba similar:
var test = { level1:{level2:{level3:''result''}}};
utils.checkObjHasKeys(test, [''level1'', ''level2'', ''level3'']); // true
utils.checkObjHasKeys(test, [''level1'', ''level2'', ''foo'']); // false
qué tal si
try {
alert(test.level1.level2.level3)
} catch(e) {
...whatever
}
Esto funciona con todos los objetos y matrices :)
ex:
if( obj._has( "something.[''deep''][''under''][1][0].item" ) ) {
//do something
}
Esta es mi versión mejorada de la respuesta de Brian.
Utilicé _has como el nombre de la propiedad porque puede entrar en conflicto con la propiedad existente (por ejemplo: maps)
Object.defineProperty( Object.prototype, "_has", { value: function( needle ) {
var obj = this;
var needles = needle.split( "." );
var needles_full=[];
var needles_square;
for( var i = 0; i<needles.length; i++ ) {
needles_square = needles[i].split( "[" );
if(needles_square.length>1){
for( var j = 0; j<needles_square.length; j++ ) {
if(needles_square[j].length){
needles_full.push(needles_square[j]);
}
}
}else{
needles_full.push(needles[i]);
}
}
for( var i = 0; i<needles_full.length; i++ ) {
var res = needles_full[i].match(/^((/d+)|"(.+)"|''(.+)'')/]$/);
if (res != null) {
for (var j = 0; j < res.length; j++) {
if (res[j] != undefined) {
needles_full[i] = res[j];
}
}
}
if( typeof obj[needles_full[i]]==''undefined'') {
return false;
}
obj = obj[needles_full[i]];
}
return true;
}});
Aquí está el fiddle
Edición ligera a esta respuesta para permitir matrices anidadas en la ruta
var has = function (obj, key) {
return key.split(".").every(function (x) {
if (typeof obj != "object" || obj === null || !x in obj)
return false;
if (obj.constructor === Array)
obj = obj[0];
obj = obj[x];
return true;
});
}
Compruebe la respuesta vinculada para usos :)
Tenía el mismo problema y quería ver si podía encontrar una solución propia. Esto acepta la ruta que desea verificar como una cadena.
function checkPathForTruthy(obj, path) {
if (//[[a-zA-Z_]/.test(path)) {
console.log("Cannot resolve variables in property accessors");
return false;
}
path = path.replace(//[/g, ".");
path = path.replace(/]|''|"/g, "");
path = path.split(".");
var steps = 0;
var lastRef = obj;
var exists = path.every(key => {
var currentItem = lastRef[path[steps]];
if (currentItem) {
lastRef = currentItem;
steps++;
return true;
} else {
return false;
}
});
return exists;
}
Aquí hay un fragmento con algunos casos de registro y prueba:
console.clear();
var testCases = [
["data.Messages[0].Code", true],
["data.Messages[1].Code", true],
["data.Messages[0][''Code'']", true],
[''data.Messages[0]["Code"]'', true],
["data[Messages][0][''Code'']", false],
["data[''Messages''][0][''Code'']", true]
];
var path = "data.Messages[0].Code";
var obj = {
data: {
Messages: [{
Code: "0"
}, {
Code: "1"
}]
}
}
function checkPathForTruthy(obj, path) {
if (//[[a-zA-Z_]/.test(path)) {
console.log("Cannot resolve variables in property accessors");
return false;
}
path = path.replace(//[/g, ".");
path = path.replace(/]|''|"/g, "");
path = path.split(".");
var steps = 0;
var lastRef = obj;
var logOutput = [];
var exists = path.every(key => {
var currentItem = lastRef[path[steps]];
if (currentItem) {
logOutput.push(currentItem);
lastRef = currentItem;
steps++;
return true;
} else {
return false;
}
});
console.log(exists, logOutput);
return exists;
}
testCases.forEach(testCase => {
if (checkPathForTruthy(obj, testCase[0]) === testCase[1]) {
console.log("Passed: " + testCase[0]);
} else {
console.log("Failed: " + testCase[0] + " expected " + testCase[1]);
}
});
//Just in case is not supported or not included by your framework
//***************************************************
Array.prototype.some = function(fn, thisObj) {
var scope = thisObj || window;
for ( var i=0, j=this.length; i < j; ++i ) {
if ( fn.call(scope, this[i], i, this) ) {
return true;
}
}
return false;
};
//****************************************************
function isSet (object, string) {
if (!object) return false;
var childs = string.split(''.'');
if (childs.length > 0 ) {
return !childs.some(function (item) {
if (item in object) {
object = object[item];
return false;
} else return true;
});
} else if (string in object) {
return true;
} else return false;
}
var object = {
data: {
item: {
sub_item: {
bla: {
here : {
iam: true
}
}
}
}
}
};
console.log(isSet(object,''data.item'')); // true
console.log(isSet(object,''x'')); // false
console.log(isSet(object,''data.sub_item'')); // false
console.log(isSet(object,''data.item'')); // true
console.log(isSet(object,''data.item.sub_item.bla.here.iam'')); // true
var a;
a = {
b: {
c: ''d''
}
};
function isset (fn) {
var value;
try {
value = fn();
} catch (e) {
value = undefined;
} finally {
return value !== undefined;
}
};
// ES5
console.log(
isset(function () { return a.b.c; }),
isset(function () { return a.b.c.d.e.f; })
);
Si está codificando en un entorno ES6 (o utilizando 6to5 ), puede aprovechar la sintaxis de la función de flecha :
// ES6 using the arrow function
console.log(
isset(() => a.b.c),
isset(() => a.b.c.d.e.f)
);
En cuanto al rendimiento, no hay ninguna penalización de rendimiento por usar el bloque try..catch
si la propiedad está establecida. Hay un impacto en el rendimiento si la propiedad no está establecida.
Considere simplemente usar _.has
:
var object = { ''a'': { ''b'': { ''c'': 3 } } };
_.has(object, ''a'');
// → true
_.has(object, ''a.b.c'');
// → true
_.has(object, [''a'', ''b'', ''c'']);
// → true