How to Find Out if a Property in an Object Exists [duplicate] - javascript

This question already has answers here:
Test for existence of nested JavaScript object key
(64 answers)
Closed 7 years ago.
Does anyone know a clean way to find out if an object property exists? Here is my example:
var test = {
a : 'west',
b : {
a : 'rest'
},
d : {
a : 'pest'
}
};
// I want to access 'a' in 'c'
typeof test.c.a; // fails!
typeof it seems can't get past the fact that 'c' doesn't exist to check if 'a' exists inside it (I've also tried jQuery.type() which also fails in the same way - I would have thought it would have error checking inside that function).
In this example of course I could simply check if 'c' exists first but in my real situation I have a large and deep object and I need to dynamically retrieve data from any potential location so it would be nice if there were a ready-made solution which didn't necessitate having to use a try-catch.
Thanks in advance!

I can't vouch for any existing functionality in any js framework for finding nested properties, but you can certainly roll your own.
hasOwnProperty is part of the ECMA script standard.
if(test.hasOwnProperty("c"))
{
console.log("test.c = " + test.c);
}
If you are looking to find deeply nested properties, then you could roll your own function to check if the nested property exists, and if so, return it.
function hasNestedProperty(testObject, properties)
{
var maxDepth = properties.length;
var i, hasProperty = false;
var currObj = testObject;
while(hasProperty && i < maxDepth)
{
if(currObj.hasOwnProperty(properties[i])
{
currObj = currObj[properties[i]]);
i ++;
}
else
{
hasProperty = false;
}
}
return hasProperty;
}

Related

JavaScript - get a property from an object or throw error if undefined [duplicate]

This question already has answers here:
if (key in object) or if(object.hasOwnProperty(key)
(9 answers)
Closed 4 years ago.
I was wondering if there was a standard library or external library (eg lodash) function that essentially does following:
function f(options) {
const x = options.x;
if (x === null || x === undefined) throw new Error('x is required option');
...
}
I have searched various key words in the lodash documentation but have yet to find something like this.
To check if a property exists, you can just write if(x in options)... Libraries exist to make tedious or difficult operations simple, This is such a simple operation that no library is needed and you'd be unlikely to find it added to a library.
While .hasOwnProperty() can work, it will only test for properties attached directly to the object in quesiton, while the in approach tests for inherited properties as well.
But, be careful about throwing errors. It's not generally something that you want to do for performance reasons. It's better to return a code or message.
var options = {
foo:42,
bar:"doesn't matter"
};
function propTest(propName, obj){
// Instead of throwing an error, return a value that indicates success or not
return (propName in obj) ? true : false;
}
console.log(propTest("foo", options));
console.log(propTest("bar", options));
console.log(propTest("baz", options));
You can write a function that iterates through an objects keys and looks for undefined ones
function CheckObjectProperties(obj)
{
for (var key in obj)
{
if(!obj[key])
{
throw new Error('Object has one or more undefined members');
}
}
}
or if you wanna check if an unknown object you can do something along the line of this. This approach is much more dynamic and reusable :D
function CheckObjectForProperties(obj, arraryOfStringProperties)
{
for(let i = 0; i < arraryOfStringProperties.length; i++)
{
let key = arraryOfStringProperties[i];
if(!obj[key])
{
throw new Error('Member not Found in Given Object.');
}
}
}
let myObject = {
x : 1,
y : 2,
z : undefined
}
let requiredProperties = ['x', 'y', 'z'];
CheckObjectForProperties(myObject, requiredProperties);

javascript access objects in an array [duplicate]

This question already has answers here:
Find object by id in an array of JavaScript objects
(36 answers)
Closed 8 years ago.
If I have something like this:
var quiz = [{
"questionID": "KC2Q4",
"correctAnswer": "KC2Q4a"
},{
"questionID": "KC2Q5",
"correctAnswer": "KC2Q5b"
}];
and have a variable that we can call "question" that has a value of a string like KC2Q4. How do I return the "correctAnswer" for the "questionID" that matches the variable "question" in a new variable "answer"?
You essentially want to iterate over your array, checking each object for the proper questionID. When you find that object, return the correctAnswer property of that object.
var question = "KC2Q4";
for( var i=0; i<quiz.length; i++ ){
if( quiz[i].questionID === question ){
return quiz[i].correctAnswer;
}
}
You should use Array.prototype.filter function (note filter() is a ECMA-Script 5.x native function: you don't need third-party libraries or frameworks!!):
var correctAnswer = "KC2Q4a";
// "filter" is like a "where". It iterates each object in your array
// and returns ones that fit the given condition as a closure:
var answersFound = quiz.filter(function(question) {
return question.correctAnswer == correctAnswer;
});
// You could verify if length > 0, but you want to be sure that
// there's only a single match for a given correct answer, because I feel
// that "correctAnswer" is like an unique id...
if(answersFound.length == 1) {
// Since there's a found answer to given "correctAnswer",
// you get the single result (i.e. the question object):
var answer = answersFound[0];
}
If you find above checking useless (in my case, I would call it defensive programming), you may retrieve the question object directly this way:
// Without the checking done in the other code listing, you've two risks:
// a. "quiz" could contain no question objects and the filter will return zero results
// meaning that getting first result array index will throw an error!
//
// b. "quiz" could contain question objects but what you're looking for isn't
// present in the so-called array. Error too!
var answer = quiz.filter(function(question) {
return question.correctAnswer == correctAnswer;
})[0];

javascript- Not outputting the result on console (level beginner) [duplicate]

This question already has answers here:
How do I loop through or enumerate a JavaScript object?
(48 answers)
Closed 6 years ago.
How do I enumerate the properties of a JavaScript object?
I actually want to list all the defined variables and their values, but I've learned that defining a variable actually creates a property of the window object.
Simple enough:
for(var propertyName in myObject) {
// propertyName is what you want
// you can get the value like this: myObject[propertyName]
}
Now, you will not get private variables this way because they are not available.
EDIT: #bitwiseplatypus is correct that unless you use the hasOwnProperty() method, you will get properties that are inherited - however, I don't know why anyone familiar with object-oriented programming would expect anything less! Typically, someone that brings this up has been subjected to Douglas Crockford's warnings about this, which still confuse me a bit. Again, inheritance is a normal part of OO languages and is therefore part of JavaScript, notwithstanding it being prototypical.
Now, that said, hasOwnProperty() is useful for filtering, but we don't need to sound a warning as if there is something dangerous in getting inherited properties.
EDIT 2: #bitwiseplatypus brings up the situation that would occur should someone add properties/methods to your objects at a point in time later than when you originally wrote your objects (via its prototype) - while it is true that this might cause unexpected behavior, I personally don't see that as my problem entirely. Just a matter of opinion. Besides, what if I design things in such a way that I use prototypes during the construction of my objects and yet have code that iterates over the properties of the object and I want all inherited properties? I wouldn't use hasOwnProperty(). Then, let's say, someone adds new properties later. Is that my fault if things behave badly at that point? I don't think so. I think this is why jQuery, as an example, has specified ways of extending how it works (via jQuery.extend and jQuery.fn.extend).
Use a for..in loop to enumerate an object's properties, but be careful. The enumeration will return properties not just of the object being enumerated, but also from the prototypes of any parent objects.
var myObject = {foo: 'bar'};
for (var name in myObject) {
alert(name);
}
// results in a single alert of 'foo'
Object.prototype.baz = 'quux';
for (var name in myObject) {
alert(name);
}
// results in two alerts, one for 'foo' and one for 'baz'
To avoid including inherited properties in your enumeration, check hasOwnProperty():
for (var name in myObject) {
if (myObject.hasOwnProperty(name)) {
alert(name);
}
}
Edit: I disagree with JasonBunting's statement that we don't need to worry about enumerating inherited properties. There is danger in enumerating over inherited properties that you aren't expecting, because it can change the behavior of your code.
It doesn't matter whether this problem exists in other languages; the fact is it exists, and JavaScript is particularly vulnerable since modifications to an object's prototype affects child objects even if the modification takes place after instantiation.
This is why JavaScript provides hasOwnProperty(), and this is why you should use it in order to ensure that third party code (or any other code that might modify a prototype) doesn't break yours. Apart from adding a few extra bytes of code, there is no downside to using hasOwnProperty().
The standard way, which has already been proposed several times is:
for (var name in myObject) {
alert(name);
}
However Internet Explorer 6, 7 and 8 have a bug in the JavaScript interpreter, which has the effect that some keys are not enumerated. If you run this code:
var obj = { toString: 12};
for (var name in obj) {
alert(name);
}
If will alert "12" in all browsers except IE. IE will simply ignore this key. The affected key values are:
isPrototypeOf
hasOwnProperty
toLocaleString
toString
valueOf
To be really safe in IE you have to use something like:
for (var key in myObject) {
alert(key);
}
var shadowedKeys = [
"isPrototypeOf",
"hasOwnProperty",
"toLocaleString",
"toString",
"valueOf"
];
for (var i=0, a=shadowedKeys, l=a.length; i<l; i++) {
if map.hasOwnProperty(a[i])) {
alert(a[i]);
}
}
The good news is that EcmaScript 5 defines the Object.keys(myObject) function, which returns the keys of an object as array and some browsers (e.g. Safari 4) already implement it.
In modern browsers (ECMAScript 5) to get all enumerable properties you can do:
Object.keys(obj)
(Check the link to get a snippet for backward compatibility on older browsers)
Or to get also non-enumerable properties:
Object.getOwnPropertyNames(obj)
Check ECMAScript 5 compatibility table
Additional info:
What is a enumerable attribute?
I think an example of the case that has caught me by surprise is relevant:
var myObject = { name: "Cody", status: "Surprised" };
for (var propertyName in myObject) {
document.writeln( propertyName + " : " + myObject[propertyName] );
}
But to my surprise, the output is
name : Cody
status : Surprised
forEach : function (obj, callback) {
for (prop in obj) {
if (obj.hasOwnProperty(prop) && typeof obj[prop] !== "function") {
callback(prop);
}
}
}
Why? Another script on the page has extended the Object prototype:
Object.prototype.forEach = function (obj, callback) {
for ( prop in obj ) {
if ( obj.hasOwnProperty( prop ) && typeof obj[prop] !== "function" ) {
callback( prop );
}
}
};
for (prop in obj) {
alert(prop + ' = ' + obj[prop]);
}
Simple JavaScript code:
for(var propertyName in myObject) {
// propertyName is what you want.
// You can get the value like this: myObject[propertyName]
}
jQuery:
jQuery.each(obj, function(key, value) {
// key is what you want.
// The value is in: value
});
Here's how to enumerate an object's properties:
var params = { name: 'myname', age: 'myage' }
for (var key in params) {
alert(key + "=" + params[key]);
}
I found it... for (property in object) { // do stuff } will list all the properties, and therefore all the globally declared variables on the window object..
You can use the for of loop.
If you want an array use:
Object.keys(object1)
Ref. Object.keys()
If you are using the Underscore.js library, you can use function keys:
_.keys({one : 1, two : 2, three : 3});
=> ["one", "two", "three"]
Python's dict has 'keys' method, and that is really useful. I think in JavaScript we can have something this:
function keys(){
var k = [];
for(var p in this) {
if(this.hasOwnProperty(p))
k.push(p);
}
return k;
}
Object.defineProperty(Object.prototype, "keys", { value : keys, enumerable:false });
EDIT: But the answer of #carlos-ruana works very well. I tested Object.keys(window), and the result is what I expected.
EDIT after 5 years: it is not good idea to extend Object, because it can conflict with other libraries that may want to use keys on their objects and it will lead unpredictable behavior on your project. #carlos-ruana answer is the correct way to get keys of an object.
If you're trying to enumerate the properties in order to write new code against the object, I would recommend using a debugger like Firebug to see them visually.
Another handy technique is to use Prototype's Object.toJSON() to serialize the object to JSON, which will show you both property names and values.
var data = {name: 'Violet', occupation: 'character', age: 25, pets: ['frog', 'rabbit']};
Object.toJSON(data);
//-> '{"name": "Violet", "occupation": "character", "age": 25, "pets": ["frog","rabbit"]}'
http://www.prototypejs.org/api/object/tojson
I'm still a beginner in JavaScript, but I wrote a small function to recursively print all the properties of an object and its children:
getDescription(object, tabs) {
var str = "{\n";
for (var x in object) {
str += Array(tabs + 2).join("\t") + x + ": ";
if (typeof object[x] === 'object' && object[x]) {
str += this.getDescription(object[x], tabs + 1);
} else {
str += object[x];
}
str += "\n";
}
str += Array(tabs + 1).join("\t") + "}";
return str;
}

Using string "constructor" as key in JavaScript object

I'm working on an Exercism JavaScript exercise and I've gotten stuck. The exercise is to create a function which loops over a string, then creates an object with each word as a key and the number of times that that word appears as the corresponding value. Simple right? Well, now I'm stuck on one of the later steps, the input string contains the word "constructor" and you need to put it into the object as a key. Here's the code I have so far, as well as the Jasmine spec which tests it:
function words(words){
count = {};
splits = words.split(" ");
for(var i = 0; i < splits.length; i++){
splits[i] = splits[i].replace(/[;:!&#$%\^,]/g, "").toLowerCase();
if([splits[i]] == ""){
continue;
}else if(count[splits.i] !== null){
count[splits[i]]++;
}else{
count[splits[i]] = 1;
}
}
return count;
};
words("constructor Constructor")
describe("words()", function() {
it("counts constructor", function() {
var expectedCounts = { constructor: 2 };
expect(words("constructor Constructor")).toEqual(expectedCounts);
});
});
Problem is, using either dot or bracket notation in the second conditional, it evaluates to true as "constructor" is inherited from the Object prototype up the chain and so it tries to increment a NaN value. I've tried to find a work around but have come up empty. And as much as I love JS, it's inheritance has it's quirks. Is there any way to prevent inheritance in this case or another work around that anyone can think of?
Instead of comparing to null to see if you've already set a property on count, use hasOwnProperty. hasOwnProperty doesn't include properties that come from up the prototype chain, only ones directly on the object.
if (count.hasOwnProperty(splits[i])) {
count[splits[i]]++;
} else{
count[splits[i]] = 1;
}

How do you access an object within an object from an argument in Javascript? [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Accessing nested JavaScript objects with string key
I have the function
function _get(name) {
return plugin._optionsObj[name] !== undefined ?
plugin._optionsObj[name] : plugin._defaults[name];
}
I would like to be able to have objects inside of my _defaults object, but then I don't know how to retrieve them but using just one set of square brackets.
i.e.
plugin._defaults = {
val1: 1,
val2: 2,
obj1: {
someVal: 3
}
}
Is it possible to access 'someVal' from the function I have above? I tried passing 'obj1.someVal' for the argument and it didn't work. Ideas?
Edit: I have found a solution and I posted it below as an answer. I've written a very nice little function to do go through the nested values with a string and I didn't have to change my function much to implement it. I hope this helps anyone in a similar situation.
I suspect that you won't always have a one-level nested object to access, so the cleaner way to do this is to use a function that traverses an object based on a string path. Here's one that is coded as a mixin for Underscore. You can then just use it like so:
_.deep(plugin._defaults, 'obj1.someVal');
This thread also has some non-Underscore alternatives.
Pass multiple arguments, and iterate over the arguments object.
function _get(/* name1, name2, namen */) {
var item = plugin._optionsObj,
defItem = plugin._defaults;
for (var i = 0; i < arguments.length; i++) {
item = item[arguments[i]];
defItem = defItem[arguments[i]];
if (item == null || defItem == null)
break;
}
return item == null ? defItem : item;
}
var opt = _get("obj1", "someVal")
I found a solution for this problem, at least one that will accommodate myself, and I'd like to share it in case it can help someone else with this problem. My biggest difficulty is that I did not know the depth of the nested value so I wanted to find a solution that would work for deeply nested objects and without requiring to redesign anything.
/* Retrieve the nested object value by using a string.
The string should be formatted by separating the properties with a period.
#param obj object to pass to the function
propertyStr string containing properties separated by periods
#return nested object value. Note: may also return an object */
function _nestedObjVal(obj, propertyStr) {
var properties = propertyStr.split('.');
if (properties.length > 1) {
var otherProperties = propertyStr.slice(properties[0].length+1); //separate the other properties
return _nestedObjVal(obj[properties[0]], otherProperties); //continue until there are no more periods in the string
} else {
return obj[propertyStr];
}
}
function _get(name) {
if (name.indexOf('.') !== -1) {
//name contains nested object
var userDefined = _nestedObjVal(plugin._optionsObj, name);
return userDefined !== undefined ? userDefined : _nestedObjVal(plugin._defaults, name);
} else {
return plugin._optionsObj[name] !== undefined ?
plugin._optionsObj[name] : plugin._defaults[name];
}
}
To retrieve objects inside of your _defaults object you'll need to improve your _get function.
For example you may pass an array of strings (each string representing a propery name) to _get to allow access to deeply nested objects.

Categories