Cain Nuke
Cain Nuke

Reputation: 3079

expected an identifier and instead saw an expression

Hi,

I have this code:

obj = {"ignoredid":"3329"},{"ignoredid":"19693"};
hit = "3329";
if (Object.values(obj).indexOf(hit) > -1) {
   console.log('has it');
} else {console.log('doesnt');}

but I get a warning that says: expected an identifier and instead saw an expression

Why is that? This is the fiddle

https://jsfiddle.net/o7u5L90h/1/

the code works fine on the fiddle despite the warning but not on my actual project (there it will always output "doesnt" no matter what) so I wonder if it will work once I get rid of the warning. What am I missing here?

Thank you.

Upvotes: 0

Views: 679

Answers (2)

Ruan Mendes
Ruan Mendes

Reputation: 92274

To answer your real question, what is happening there is that the statement obj = {ignoredid : 3329},{ignoredid : 19693}; does not cause a syntax error but does not do what you expect it to do.

Though it's not clear what you expected to happen 😁. That's why a lint is warning that expected an identifier and instead saw an expression

It's being interpreted as something close to the following:

obj = {ignoredid : 3329}, {ignoredid : 19693};
console.log(JSON.stringify(obj));

// Is interpreted as
obj = {ignoredid : 3329}
{ignoredid : 19693}
console.log(JSON.stringify(obj));

// Or
((obj = {ignoredid : 3329}), {ignoredid : 19693});
console.log(JSON.stringify(obj))

In both cases, the literal {ignoredid : 19693} is being discarded and not used by the program.

Note that if you started writing code that was using const/let or even var, you wouldn't have this problem and you'd be told you have a real syntax error and you wouldn't get this weird behavior. That is because a VariableDeclaration is not an Expression, and expressions separated by commas is what's happening here. See the end of the answer for further details.

Uncaught SyntaxError: Invalid destructuring assignment

const obj = {ignoredid : 3329}, {ignoredid : 19693};
console.log(JSON.stringify(obj));

Explaining current behavior

If you intended it as obj = {ignoredid : 3329, ignoredid : 19693};, that would mean that the obj would be {ignoredid : 19693}, that is, the last property with the same name wins out.

This is why you were always getting console.log('doesnt'), your object did not contain a value of 3329 only 19693;

Solution

As suggested by tark, Umitigate and me, you should use an array. I just wanted to answer the real question since the behavior is bit odd even outside of your quirky declaration😜

Gorier Technical Details Explaining Error Message

If you analyze the syntax tree of your example, you'll notice that the body of the program is an ExpressionStatement but it does not contain an assignment directly, instead, it contains a nested SequenceExpression which contains a separate AssignmentExpression and an ObjectExpression which is not what you intended

However, if you analyze the syntax tree of obj = {"ignoredid":"3329"};, you'll notice that there's an AssignmentExpression nested directly in the first ExpressionStatement of the program

So the message is indicating that it expected an Assignment but instead saw an Expression

Upvotes: 1

tarkh
tarkh

Reputation: 2549

Maybe you want array of objects? Then you can do something like this

// Helper function to check array of objects
const hasIt = (obj, val) => {
  for(const v of obj) if(v['ignoredid'] === val) return true;
  return false;
}

// Define array of objects
const obj = [{"ignoredid":"3329"},{"ignoredid":"19693"}];

// Test it
if(hasIt(obj, "3329")) console.log('has it');
else console.log('doesnt');

Or with more recent approach

// Define array of objects
const obj = [{"ignoredid":"3329"},{"ignoredid":"19693"}];

// Test it
if(obj.find(o => o.ignoredid === '3329')) console.log('has it');
else console.log('doesnt');

Upvotes: 1

Related Questions