6

I am writing a minigame about javascript thruthiness and I found something strange.

eval('{}=={}') // error

{}=={} // false in the console but is an error in a source file

eval('[]==[]') // no error => false

eval('{}') // no error => undefined

eval('({})') // no error => Object

eval('[]') // no error => Array

Why is eval('{}=={}') an error and why is evaling things containing {} so inconsistent?

Samuel Danielson
  • 5,231
  • 3
  • 35
  • 37
  • 7
    `{}` can mean an empty object literal, *or* a code block with zero statements within. Context is used to tell the difference, and the errors are caused by the browser "guessing" incorrectly. `({})` fixes it, as in this case `{}` *cannot* be a code block and therefore *must* be an empty object literal. – Niet the Dark Absol Aug 04 '16 at 16:12
  • Ah, code block vs literal. Thanks. – Samuel Danielson Aug 04 '16 at 16:15
  • 2
    `{}=={}` is also an error in regular code. The console does behave differently as it will evaluate your `{}=={}` code as if you would write `({}=={})`, the console does some different assumptions about your code context then as if you would writ it in a regular code file. – t.niese Aug 04 '16 at 16:16
  • 1
    For a similar example of the browser "guessing", see IIFEs - `(function() {...})()` or sometimes `!function() {...}()` to force a function expression as opposed to a function declaration. – Niet the Dark Absol Aug 04 '16 at 16:17
  • 1
    @NiettheDarkAbsol This has nothing to do with the browser guessing. –  Aug 04 '16 at 16:39

1 Answers1

1

Overview

Well, within JavaScript, every Object is different. Anytime an object comes into play, it will never ==/=== another object. Even if they are identical

Examples

{}=={} // false

[]==[] // false

[1][0]==[1][0] // true

{id: 1}.id=={id: 1}.id // true

Ways to get around this

One way is to use JSON.stringify to get the string value of whatever argument is given

// Option 1
JSON.stringify({}) == JSON.stringify({}) // true
JSON.stringify([]) == JSON.stringify([]) // true

Another way is to use this function I created that compares two objects/arrays/strings/etc

// Option 2
Object.prototype.forEach = function forEach(callback) {
    for (i in this) {
        if (!this.hasOwnProperty(i)) continue;
        callback(i, this[i])
    }
}

Object.equals = function equals(obj1,obj2) {
    var match = true;
    if (typeof obj1 !== typeof obj2) {
        return false;
    } else if (typeof obj1 !== "object" && typeof obj2 !== "object") {
        return obj1 === obj2;
    } else if (JSON.stringify(obj1) == JSON.stringify(obj2)) {
        return true;
    }
    obj1.forEach((value,key) => {
        console.log(key, value)
        if (obj2[key] !== value) {
            match = false;
            return;
        }
    })
    return match;
}


Object.equals({},{}) // true
Object.equals("hello","goodbye") // false
Object.equals([],{}) // true because both of these different items are empty instances of objects.
RedYetiDev
  • 404
  • 3
  • 16