First of all, you don't need to check for both property in object
&& typeof obj[property] == 'object'
, you can only use the typeof
to take care of both checks. The reason is that, if that obj.property
doesn't exist, typeof
will return undefined
.
Therefore, you can modularize your approach by writing a small utility function that checks if something is an object:
function isObject(o) {
return typeof o == 'object' && o !== null; // take care of the corner case that typeof null == 'object'
}
Then just use it on your necessary object chain to find a property by checking that all of its owning objects exists:
function getChecklistUrl() {
if(isObject(dataLayerObject) &&
isObject(dataLayerObject.config) &&
isObject(dataLayerObject.config.checklist)) {
return dataLayerObject.config.checklist;
}
return null;
}
var dataLayerObject = {
config: {
checklist: ['array of stuff']
}
}
function isObject(o) {
return typeof o == 'object' && o !== null;
}
function getChecklistUrl() {
if (isObject(dataLayerObject) &&
isObject(dataLayerObject.config) &&
isObject(dataLayerObject.config.checklist)) {
return dataLayerObject.config.checklist;
}
return null;
}
console.log(getChecklistUrl()[0]);
This makes the code more organized and easier to read, IMHO.
You can also do something like a getter for your objects that take a dot-separated string and return you the property or null if the property doesn't exist:
function getObjProperty(obj, propString) {
if(!isObject(obj) || !propString || typeof propString != 'string') {
return null; // make sure obj is an object and propString is a non-empty string
}
var props = propString.split('.');
for (var i = 0, l = props.length; i < l; i++) {
var p = props[i];
if(!isObject(obj[p])) { return null; } // if current property isn't an object, return null
obj = obj[p]; // otherwise update the object to the next one down the property chain
}
return obj;
}
You would use it like: getObjProperty(dataLayerObject, 'config.checklist');
var dataLayerObject = {
config: {
checklist: ['array of stuff']
}
};
function isObject(o) {
return typeof o == 'object' && o !== null;
}
function getObjProperty(obj, propString) {
if (!isObject(obj) || !propString || typeof propString != 'string') {
return null;
}
var props = propString.split('.');
for (var i = 0, l = props.length; i < l; i++) {
var p = props[i];
if (!isObject(obj[p])) { //
return null;
} // if current property isn't an object, return null
obj = obj[p]; // otherwise update the object to the next one down the property chain
}
return obj;
}
console.log(getObjProperty(dataLayerObject, 'config.checklist'));
Or you can achieve this with a fairly straightforward recursive method
NOTE:
The examples above check the prototype chain as well. If you don't want this, you should use hasOwnProperty
when checking if a property is an object to also check that the property exists on the testing object.
Prefix's answer shows one variation of such an approach.