0

I need to check whether several specific properties exist in an object. And for that I have two questions:

  1. How am I generally supposed to check for several existing properties in JavaScript?
  2. Is there a shortcut in CoffeeScript to do this in an elegant way?

My javascript solution would be:

if(obj && obj.pOne && obj.pTwo && obj.pThree) doStuff();

In coffee script that would be no shorter:

if obj and obj.pOne and obj.pTwo and obj.pThree then doStuff()

Don't get mislead here, it's not going to work:

And then I ran into the in operator for if clauses (which I never used for such checks). Is this the right way to do what I want to achieve? Or is that some sort of no-go, or is there a better/cleaner solution to that?

My code would then look like this:

if(obj && ('pOne' && 'pTwo' && 'pThree' in obj)) doStuff();

and coffeescript like this:

if obj and ('pOne' and 'pTwo' and 'pThree' of obj) then doStuff()

1
  • !!!DON'T COPY MY SECOND SUGGESTION TO USE THE in OPERATOR TOGETHER WITH && CONCATENATION!!! I just found out the above solution with in doesn't do at all what I want to achieve! It only checks the last property since this is the result of the && concatenation. I should have known it... seems I have to stick with the first solution, right? Commented Nov 20, 2013 at 9:14

2 Answers 2

2

Your first line is what you want. There's nothing wrong with this, as it is. Maybe consider writing your function differently if you think you need to check 4 things before calling a function.

if(obj && obj.pOne && obj.pTwo && obj.pThree) doStuff();

See this: Why Defensive Programming is Rubbish

PS. Your last examples are no good and don't evaluate the way you think they do


Consider rewriting the function to make it nicer to use

var doStuff = function(obj) {
  obj        = obj        || {};
  obj.pOne   = obj.pOne   || "pOneDefault";
  obj.pTwo   = obj.pTwo   || "pTwoDefault";
  obj.pThree = obj.pThree || "pThreeDefault";

  console.log(obj);
};

doStuff();
// {pOne: "pOneDefault", pTwo: "pTwoDefault", pThree: "pThreeDefault"}

doStuff({pOne: "foo"});
// {pOne: "foo", pTwo: "pTwoDefault", pThree: "pThreeDefault"}

doStuff({pTwo: "bar"});
// {pTwo: "bar", pOne: "pOneDefault", pThree: "pThreeDefault"}

doStuff({pTwo: "hello", pThree: "world"});
// {pTwo: "hello", pThree: "world", pOne: "pOneDefault"}
Sign up to request clarification or add additional context in comments.

1 Comment

I agree on the defensive programming article, but it doesn't apply here since the object I receive is a parsed config file from the user. And I do the checks to notify him whether he has all the necessary properties defined or else stop the execution of the program.
2

pOne in obj is not the same as obj.pOne. For example, for obj = { a: 0 }, a in obj is true, but obj.a is falsy.

('pOne' && 'pTwo' && 'pThree' in obj) does not mean what you think; it evaluates as ('pOne' && 'pTwo' && ('pThree' in obj)), which is same as true && true && ('pThree' in obj).

Although verbose, if you want to catch the difference between falsy values and nonexistent keys, this is still the best way:

if (obj && 'pOne' in obj && 'pTwo' in obj && 'pThree' in obj)

If you think that the properties might be inherited, then using obj.hasOwnProperty('pOne') instead of 'pOne' in obj is better still.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.