0

How to check if a variable is equal to [{}] in Node JS?

Tried all possible ways. But no luck. Help is much appreciated.

Thanks, Varun

Varun kumar
  • 2,849
  • 3
  • 15
  • 9

4 Answers4

2

I admit that this is not the most optimal solution, but a quick JSON string compare could work:

var a = [{}]
JSON.stringify(a) == '[{}]' //true

Otherwise, you'll want to implement a more robust object/array comparison such as: Tomáš Zato's answer in How to compare arrays in JavaScript?

Or use a lib such as underscore.js.

Community
  • 1
  • 1
Protostome
  • 5,569
  • 5
  • 30
  • 45
  • but `JSON.stringify([new RegExp]) === '[{}]'` – vkurchatkin Nov 23 '13 at 20:10
  • @vkurchatkin: very true—shows that nearly all those ad-hoc strike-of-a-genius/script-kiddy-solutions have their unforeseen glitches. **JSON.stringify will fail when you try to compare two objects that have the same key/value pairs that were added in a different order** (the general agreement in JS being that while ordering of keys is arbitrary as per the spec, it is still preserved by all current VMs and may be exploited (when you know what you do); however, the consensus is rather that ordering should not affect equality. `JSON.stringify` breaks this and other assumptions in *some* cases). – flow May 28 '14 at 14:28
1

If you are comparing you can use deepEqual from assert :

> a =[{}]
[ {} ]
> assert.deepEqual(a,[{}])
undefined
>

This can be used for equivalence in object structures. Almost suitable, the caveat is that it will treat unnested [] and {} same.

> assert.deepEqual(a,[[]])
undefined
> assert.deepEqual({},[])
undefined

Update

deepEqual does not check for strict equality. This however is good for testing if two objects have similar nested structures, barring the above caveat which would apply for leaf nodes in the object. E.g. 2nd case

> assert.deepEqual({a:[{b:[]}]},{a:[{b:[]}]})
undefined
> assert.deepEqual({a:[{b:[]}]},{a:[{b:{}}]})
undefined
> assert.deepEqual({a:[{b:[]}]},{a:[{c:[]}]})
AssertionError: {"a":[{"b":[]}]} deepEqual {"a":[{"c":[]}]}

This comes in handy when checking for object structures.

user568109
  • 47,225
  • 17
  • 99
  • 123
  • not sure why you would suggest a method that demonstrably fails; for all practical purposes, you do not want `[{}]` to equal `[[]]`, or `{}` to equal `[]`. it's really sad that so many people (including myself until a short while ago) are deluded by the NodeJS docs to believing that `assert.deepEqual` performs a meaningful, deep equality test, which it does not. nerds will try to tell you to *read the docs*, but marketing people will tell you when you sell a product that has 'deepEqual' written all over it and 'coercive equality' in the fine print, they'll still buy. – flow May 28 '14 at 12:00
  • I never intended to use it for strict equality match, I could see it fails for that. My main use case was testing for object structures. Keeping in mind that {} will be equal to []. A nested structure could be equivalent only if leaf elements are [] or {} whilst rest higher structure is identical. Basically it is capable of matching nested structures minus the leaf level elements. – user568109 May 29 '14 at 05:45
1

Oh, it's so simple :

Array.isArray(obj) //is really an array, no array-like object
  && obj.length === 1
  && Object.keys(obj).length === 1 //doesn't have  anything enumerable attached 
  && typeof obj[0] === 'object' // is an object
  && Object.keys(obj[0]).length === 0 // doesn't have enumerable properties
  && obj[0].__proto__ === Object.prototype // direct ancestor of Object
vkurchatkin
  • 13,364
  • 2
  • 47
  • 55
0

i recommend against using assert.equal and assert.deepEqual—they're doing coercing (==) comparisons (this is officially justified by the relevant CommonJS specs, but i think they're broken). most of the time, you don't want [ 3 ] to equal [ '3' ], which is what assert.deepEqual will tell you.

instead, use e.g. https://github.com/jkroso/equals, which (1) works for both primitive values and lists and objects, and (2) lets you check even objects with circular references.

@vkurchatkin i don't find your solution simple—it's quite a bit of code that's tailored for a single, very specific use case. also, typeof is known to have some gotchas—specifically, it fails for arrays, and __proto__ is a deprecated property (use Object.getPrototypeOf instead).

testing for equality in JavaScript is quite a recurrent problem that is, sadly, not adequately addressed within NodeJS and other JS VMs (i believe it should be). my recommendation is to use a well-tested library that does both primitive and object equality testing with a single function, preferably one that is robust enough not to fail with circular references.

ideally, you don't want to see anything more complex than equals( d0, d1, d2, ... ) in your application code—anything more is a violation of the Principle of Separation of Concerns.

Community
  • 1
  • 1
flow
  • 3,624
  • 36
  • 48
  • well, that was sarcasm, actually – vkurchatkin May 28 '14 at 14:52
  • JavaScript has its quirks. The specs can be lacking or incorrect some times, for which the developer has to compensate. But standards can be improved. Let's hope we have a deepstrictequal counterpart by 0.12. Until then you can use equals. – user568109 May 29 '14 at 05:42
  • @vkurchatkin i took it literally, but i'm relieved you said that with tongue-in-cheek. – flow May 29 '14 at 16:54