Coffeescript isn't empty object

coffeescript

Solution

CoffeeScript's `is` (AKA `==`) is just JavaScript's `===` and `isnt` (AKA `!=`) is just JavaScript's `!==`. So your condition:

if toUpdate isnt {}

will always be true since `toUpdate` and the object literal `{}` will never be the same object.

However, if `@find` could return a known "empty" object that was available in a constant, then you could use `isnt`:

EMPTY = {}

find: ->
    # ...
    EMPTY

and later:

if toUpdate isnt EMPTY
    #...

For example, consider this simple code:

a = { }
b = { }
console.log("a is b: #{a is b}")
console.log("a isnt b: #{a isnt b}")

That will give you this in your console:

a is b: false
a isnt b: true

But this:

class C
    EMPTY = { }
    find: -> EMPTY
    check: -> console.log("@find() == EMPTY: #{@find() == EMPTY}")

(new C).check()

will say:

@find() == EMPTY: true

Demo: http://jsfiddle.net/ambiguous/7JGdq/

So you need another way to check if `toUpdate` isn't empty. You could count the properties in `toUpdate`:

if (k for own k of toUpdate).length isnt 0

or you could use the special `EMTPY` constant approach outlined above. There are various other ways to check for an empty object, Ricardo Tomasi​ has suggested a few:

- Underscore offers `_.isEmpty` which is basically the `for` loop approach with some special case handling and a short circuit.

- Underscore also offers `_.values` so you could look at `_(toUpdate).values().length`. This calls `map` internally and that will be the native `map` function if available.

- You could even go through JSON using `JSON.stringify(toUpdate) is '{}'`, this seems a bit fragile to me and rather round about.

- You could use `Object.keys` instead of the `for` loop: `Object.keys(toUpdate).length isnt 0`. `keys` isn't supported everywhere though but it will work with Node, up-to-date non-IE browsers, and IE9+.

- Sugar also has `Object.isEmpty` and jQuery has `$.isEmptyObject`.

A short-circuiting `for` loop appears to be the quickest way to check emptiness:

(obj) ->
    for k of toUpdate
        return true
    false

That assumes that you don't need `own` to avoid iterating over the wrong things. But given that this is just a test suite and that an emptiness test almost certainly won't be a bottle neck in your code, I'd go with whichever of Underscore, Sugar, or jQuery you have (if you need portability and have to deal with the usual browser nonsense), `Object.keys(x).length` if you know it will be available, and `(k for own k of toUpdate).length` if you don't have the libraries and have to deal with browser nonsense and aren't certain that `toUpdate` will be a simple object.

Problem

Possible Duplicate: is object empty? ``` update: (id, data) -> toUpdate = @find(id) if toUpdate isnt {} console.log "hi mom" console.log toUpdate toUpdate.setProperty(key, value) for own key, value of data return toUpdate find:(id) -> result = record for record in @storage when record.id is id return result or {} ``` Given the following Mocha tests ``` describe '#update', -> it 'should return an updated record from a given id and data when the record exists', -> boogie = createData() archive = new Archive("Dog") dog = archive.create(boogie) result = archive.update(1, {name:"Chompie", age:1}) result.name.should.eql "Chompie" result.age.should.eql 1 result.emotion.should.eql dog.emotion it 'should return an updated record from a given id and data when the record does not exist', -> boogie = createData() archive = new Archive("Dog") dog = archive.create(boogie) result = archive.update(50, {name:"Chompie", age:1}) result.should.not.exist ``` The result is ``` Archive #update should return an updated record from a given id and data when the record exists: hi mom { id: 1, validationStrategies: {}, name: 'Boogie', age: 2, emotion: 'happy' } ✓ Archive #update should return an updated record from a given id and data when the record exists: 1ms Archive #update should return empty when the record does not exist: hi mom {} ✖ 1 of 13 tests failed: 1) Archive #update should return empty when the record does not exist: TypeError: Object #<Object> has no method 'setProperty' ``` ...surprising, isnt it?

Original source

Related problems