jashkenas / coffeescript

Unfancy JavaScript
https://coffeescript.org/
MIT License
16.49k stars 1.98k forks source link

for in #336

Closed TomasM closed 14 years ago

TomasM commented 14 years ago

Hi,

How can I "for in" an object thought ALL the properties?

Currently:

for p of Obj

translates into:

for (p in _a) { if (__hasProp.call(_a, p)) { }}

I don't want the __hasProp check. Is there a way to do this without inline Javascript?

Thanks

jashkenas commented 14 years ago

Hi TomasM. There isn't currently a syntax for the naked property enumeration. Can you tell us a little about what you're trying to write? Is this for an inheritance library, or something along those lines?

TomasM commented 14 years ago

I'm writing a framework with KVC & KVO features. I'm borrowing alot from SproutCore.

In a class declaration I write:

class A extends HasObservableFunctionality
  prop1: 'b',
  prop2: 'c'
  func: ( ->
    ...
  ).observes('prop1', 'prop2')

function observes looks like this:

Function::observes: (args...) ->
  @_publishers: args
  @

In HasObservableFunctionality constructor I loop through all properties searching for functions that have _publishers property. And create observers...

Could there be a better way to do this?

I guess this is a not so common case and I would be fine staying with inline Javascript.

Thanks

jashkenas commented 14 years ago

That's a very interesting use case, but wouldn't it work to just loop through the location you want to search -- namely, A.prototype ?

class HasObservableFunctionality
  constructor: ->
    for key, val of this.constructor.prototype
      if val._publishers
        ...
TomasM commented 14 years ago

That would work, but if I have:

class B extends A
  func2: ( ->
    ...
  ).observes('prop1')

then

this.constuctor.prototype

in HasObservableFunctionality's constuctor will not give me what I want. It will only give me func2, but not func.

Could there be anything else I'm not seeing that I could use instead of a naked property enumeration?

jashkenas commented 14 years ago

Sure ... how about having .observes() be a method that exists on the HasObservableFunctionality class, instead of on the Function class itself. Seems cleaner, and then you get your list of observed functions for free.

class HasObservableFunctionality
  observes: (function, properties...) ->
    @observers.push {func: function, properties}
TomasM commented 14 years ago

Thanks for the suggestion.

But this way you would need to define the observers in the class constructor. Not to mention that the syntax would be prolonged, but also all properties associated with a particular method would not be immediately obvious, like for example here:

func: ( ->
   ...
).observes('*').observes_before('prop')

# .observes_before() defines that the observer 
# needs to fire BEFORE the property changes

func2: ( ->
 ...
).property().readonly()

I think I will stay with the way I do it now. The inline js part is only a one-liner. But perhaps a syntax should exist for bare enumeration.

BTW, coffeescript looks GOOOD!