Support for REAL Getters and Setters Please....

721 views
Skip to first unread message

EisenbergEffect

unread,
Dec 18, 2012, 1:03:25 PM12/18/12
to knock...@googlegroups.com
ES5 compatible runtimes have support for real getters and setters in the language (some pre-SE5 runtimes have non-standard mechanisms for achieving this as well). I'd really like to be able to use that to create observable properties. Properties should be properties, not functions. This is my chief complaint with Knockout as I've seen it cause serious maintainability and extensibility issues in multiple projects now. I really am pleased with Knockout, but this issue is a big one. And as time passes, it's going to become more of an issue.

What's the chance of this happening now or ever? If it's something that could be considered sooner, I'd be willing to put some money behind it. I bet I could find some other companies that would invest into getting this done as well.

Michael Latta

unread,
Dec 18, 2012, 1:17:11 PM12/18/12
to knock...@googlegroups.com
My understanding is that ES6 is not due until late 2013, and browser vendors may take even longer to support it. Is there a pressing need in your environment for this? if so what browser are you targeting that supports it?

Michael

On Dec 18, 2012, at 11:03 AM, EisenbergEffect <r...@bluespireconsulting.com> wrote:

> ES5 compatible runtimes have support for real getters and setters in the language (some pre-SE5 runtimes have non-standard mechanisms for achieving this as well). I'd really like to be able to use that to create observable properties. Properties should be properties, not functions. This is my chief complaint with Knockout as I've seen it cause serious maintainability and extensibility issues in multiple projects now. I really am pleased with Knockout, but this issue is a big one. And as time passes, it's going to become more of an issue.
>
> What's the chance of this happening now or ever? If it's something that could be considered sooner, I'd be willing to put some money behind it. I bet I could find some other companies that would invest into getting this done as well.
>
> --
>
>

EisenbergEffect

unread,
Dec 18, 2012, 2:38:36 PM12/18/12
to knock...@googlegroups.com
I'm not talking about ES6 or Harmony. I'm talking about ES5 which is implemented in every major browser today. These features are in IE9 and above and have been in Chrome, FF and Safari for some time. They are implemented in mobile browsers and they are available in a non-standard form in many earlier browsers as well. I'm targeting all modern browsers. They all support it. Yes, there is a pressing need for this :)

Michael Latta

unread,
Dec 18, 2012, 2:42:44 PM12/18/12
to knock...@googlegroups.com
My mistake.  I miss-read your posting.

Michael

--
 
 

EisenbergEffect

unread,
Dec 18, 2012, 3:06:58 PM12/18/12
to knock...@googlegroups.com
No problem. It can be confusing. I'm not referring to get/set as part of the language syntax, but rather Object.defineProperty which is available as part of the platform's capabilities.

anders.m...@gmail.com

unread,
Dec 18, 2012, 5:19:07 PM12/18/12
to knock...@googlegroups.com
I'm curious what kind of problems you have run into in your projects.

Roy Jacobs

unread,
Dec 19, 2012, 4:17:53 AM12/19/12
to knock...@googlegroups.com, anders.m...@gmail.com
One of the more obvious problems is that any KO observable behaves like a function, so the consumer of your viewmodel needs to be aware which properties are observables (and are accessed through a function), and which are not (and are accessed directly).

anders.m...@gmail.com

unread,
Dec 19, 2012, 4:40:20 AM12/19/12
to knock...@googlegroups.com, anders.m...@gmail.com
Yes, but its not necessary a bad thing. In WPF you use standard properties but the setter needs to call PropertyChanged(() => MyProp) to notify the view that the value has changed. This is not very DRY. Also in larger projects its actually good to distinct observable properties from the ones that are not, this because some dev's are lazy and that can cause event bubbling from hell.

But yes, many, many Stackoverflow questions spawn from problems grasping KO observables

rpn

unread,
Dec 19, 2012, 10:10:00 AM12/19/12
to knock...@googlegroups.com
I have always thought that to properly support getters/setters, we would need to make the observability part of Knockout into a module that could be swapped out with a different implementation.  Then, rather than breaking existing code and potentially supporting multiple code paths in KO core, it could be an extensibility point and developers could choose to use a plugin that supports getters/setters.  Maybe the "plugin" would be part of the core or maybe it would be an external library.

However, I wonder if there are clever ways to get the user experience now without big changes to the core.

Maybe something like:  http://jsfiddle.net/rniemeyer/uUxWt/.  The fiddle was just a 10 minute experiment, so obviously the code is somewhat naive, as it does not take into account observableArrays, writeable computeds, and likely other concerns as well.  Certainly there are other directions that you could go with the actual implementation of taking a POJO and making it observable in this way (return a clone, do all properties by default, etc.).   It could also attempt to work with older browsers that have non-standard ways of implementing getters/setters too.

EisenbergEffect

unread,
Dec 19, 2012, 10:36:20 AM12/19/12
to knock...@googlegroups.com
I tried something almost like that but it didn't work for me. I think I wrapped the get/set functions around observables instead of making them the same. That's interesting. In any case, I'd love to have the observability be separate so that you could pick different implementations based on your target and preferences. That would be cool. As for myself, I don't ever work on projects which aren't targeting ES5 browsers, so I would always pick the get/set version. It would be important that an frameworks or addons to knockout could be coded to work regardless of what mechanism the consumer is using. Your above example would work pretty well for my needs actually, if we could get arrays working. It seems like that would be tricky...What are your thoughts on that?

rpn

unread,
Dec 19, 2012, 12:40:54 PM12/19/12
to knock...@googlegroups.com
I think that there are definitely some challenges that would need to be overcome to make what I had above work in a robust manner.  In that code, you no longer have the ability to operate on the observable itself.  Would need to figure out how you would be able to manually subscribe to an observable.  ko.isObservable would also return false now, which would likely break plenty of code. Arrays would be challenging too.  The actual array would need to have all of its array methods replaced with ones that can call valueHasMutated on the actual observable.  The setter would have to make sure that this was true too, as you could just set it to a new array.

I will have to play with it a bit more and see what is possible.

EisenbergEffect

unread,
Dec 19, 2012, 1:19:35 PM12/19/12
to knock...@googlegroups.com
Definitely keep me posted. I'm pretty sure there's a lot of people that would be interested in this. Do you have any estimation as to time/effort in refactoring knockout to have pluggable implementation providers as described above? If we could get a rough estimate (from someone like you or Steve), I might be able to scrounge up funding to have it done...

EisenbergEffect

unread,
Dec 21, 2012, 1:45:38 PM12/21/12
to knock...@googlegroups.com
Ok. I've figured out ways to handle subscription and isObservable and isComputed. Essentially, we can use the other ES5 descriptor functions to get back the data, so it could be done by altering and adding utility methods to ko. Here's my fiddle which demonstrates it quickly through console.log: http://jsfiddle.net/EisenbergEffect/uLmcP/

Now, if we can fix up observable arrays. We might be in business...

rpn

unread,
Dec 21, 2012, 4:56:06 PM12/21/12
to knock...@googlegroups.com
That is a clever way to get back to the observable.   At least it would be possible to write a "subscribe" wrapper that could still create subscriptions.  Makes me wonder if there is a way we could use a custom binding provider to make sure that the bindings get the real observables and flow through the system as normal.

The arrays would be the next thing. I'll try to take a look at that part this weekend.  Interesting stuff.

rpn

unread,
Dec 27, 2012, 12:43:30 AM12/27/12
to knock...@googlegroups.com
Here is a little bit more with arrays: http://jsfiddle.net/rniemeyer/mrCSH/.  Next it would probably need some helper functions to call "subscribe" and a better way to recursively make things observable.

Kind of thinking still about how a custom binding provider might help.  Might be able to turn things into observables "just-in-time", as they are bound.  It might be interesting to see how that would feel.  There are certainly uses for observables that are not actually bound, so there would have to be other options too.

EisenbergEffect

unread,
Jan 2, 2013, 9:10:17 AM1/2/13
to knock...@googlegroups.com
The idea of lazy observable generation is one that I've thought about, but I think it's secondary to getting the core functionality in place. It looks like the implementation is coming along and could be quite nice. Here's a couple of things left:

1. Handling of array indexing. This isn't a big one since ko's observables don't do it. But, it might be nice to create an alias like getItem/setItem that you could use to set by index which would also cause the change notifications to fire. This could optionally be shimmed into the native array so that one could use indexing in the same way without having to know whether or not it was an observable array.
2. Handling of array length. I haven't tested binding against that. So if might already work. If not we could use a similar tactic as described for indexers.
3. Transparent binding in custom binding handlers. In a custom binding handler, it's common to call ko.utils.unwrapObservable(valueAccessor()) We would need to ensure that this works properly regardless of what type of observable it is. Maybe it already does I haven't tested, but wanted to mention that. We don't want to break anyone's existing binding handlers because of how the observables are implemented.
4. Need helpers for subscribe/unsubscribe that work against any type of observable too.

EisenbergEffect

unread,
Jan 2, 2013, 9:40:20 AM1/2/13
to knock...@googlegroups.com
I did some quick testing and it looks like .length and custom binding handlers already work just fine :)  So, I guess the only real thing we need is a subscribe/unsubscribe helper. Pretty cool stuff.

EisenbergEffect

unread,
Jan 2, 2013, 9:55:44 AM1/2/13
to knock...@googlegroups.com
Here's the updated fiddle that shows the confirmation: http://jsfiddle.net/EisenbergEffect/MgkmZ/
Message has been deleted

Anders Malmgren

unread,
Jan 2, 2013, 10:07:28 AM1/2/13
to knock...@googlegroups.com
Nice work Ryan, there are a lot of custom libraries that will break though. For example my Convention library does not work anymore (Two way bindnig for inputs does not work)

http://jsfiddle.net/mrCSH/8/

rpn

unread,
Jan 2, 2013, 10:10:04 AM1/2/13
to knock...@googlegroups.com
I think that there would still likely be issues with custom bindings that write to observables.  Plenty of code like:

if (ko.isObservable(value)) {
  value
("some value");
}

or

if (ko.isObservable(value)) {
  value.subscribe
(someFunction);
}

Possibly problems with other complex custom bindings that do things like add sub-observables to the original observable and places where people use an observable directly as a handler (expect it to be a function).

It would be nice if it would "just work", but that seems like it might be challenging.  I think that a custom binding provider might work where we would use the descriptor trick to pass the actual observable on to the bindings.  It would require a lot of parsing though, because we need access to the property name and the parent object  (can't just be given a string and understand if it has/had a getter/setter).  

Rob Eisenberg

unread,
Jan 2, 2013, 10:12:07 AM1/2/13
to knock...@googlegroups.com
Is there a way to make any relatively minor changes to KO itself to enable it?
> --
>
>



--
Rob Eisenberg,
Blue Spire Consulting, Inc.
Caliburn Project
850.264.3996

rpn

unread,
Jan 2, 2013, 10:22:27 AM1/2/13
to knock...@googlegroups.com, r...@bluespire.com
Possibly.  Ultimately that is one thing that I would like to get out of this exercise (an understanding of the minimum set of core changes that could make this work).  I think that it is good to also pursue how it can work in a "plug-in" model with the current core, if possible.  

I think that creating utility functions for subscribe/unsubscribe would be straightforward.  Too bad that many of these APIs would really need to deal with a parent object and a property name as a string.  Not as clean as the observable APIs for this part of it.  

nino.p...@gmail.com

unread,
May 8, 2013, 6:01:04 AM5/8/13
to knock...@googlegroups.com, r...@bluespire.com
I second what the OP said, having properties written as functions is a major annoyance in KnockOut. I use KnockOut from C# and the resulting code is just too verbose.

The solution proposed by Ryan is fantastic. You take a simple class and *puff* magically it becomes and observable model with properties supported.

I hope the code will be further developed and incorporated in knockout (as a plugin or else).

Casey Corcoran

unread,
May 8, 2013, 8:46:10 AM5/8/13
to knock...@googlegroups.com
I disagree, so much of Knockout already feels like "magic" having getters and setters will only make it more so. Kidding… sort of.

I'm curious as to how it's a "major annoyance" and too verbose? Parens seem obvious to me, you know that you're dealing with an observable and IMHO not a big deal.

One of my favorite things about Knockout is that it makes very little in the way of assumptions. IMHO It does what it does and encourages the dev to solve problems and figure out better ways of approaching things.

I'm genuinely curious to see some code thats majorly verbose and annoying because of the current implementation, and how it would be improved with getter/setters.

-- 
Casey Corcoran
Sent with Sparrow

--
You received this message because you are subscribed to the Google Groups "KnockoutJS" group.
To unsubscribe from this group and stop receiving emails from it, send an email to knockoutjs+...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.
 
 

Jim Panse

unread,
May 13, 2013, 7:25:02 PM5/13/13
to knock...@googlegroups.com
You definitely got my vote for this one. The majority (though not all) of our projects exclusively target ES5 compatible browsers and it would be a real productivity/maintainability boost if properties would be ... well ... properties.

Rob Eisenberg

unread,
May 14, 2013, 8:54:12 AM5/14/13
to knock...@googlegroups.com
FYI, We've got something coming in Durandal in the next month or so for this.. I'm trying it out on a real project now and working out the kinks before I make it official.


On Mon, May 13, 2013 at 7:25 PM, Jim Panse <bit...@googlemail.com> wrote:
You definitely got my vote for this one. The majority (though not all) of our projects exclusively target ES5 compatible browsers and it would be a real productivity/maintainability boost if properties would be ... well ... properties.

--
You received this message because you are subscribed to a topic in the Google Groups "KnockoutJS" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/knockoutjs/7MDK111-3AA/unsubscribe?hl=en-US.
To unsubscribe from this group and all its topics, send an email to knockoutjs+...@googlegroups.com.

For more options, visit https://groups.google.com/groups/opt_out.





--
Rob Eisenberg,
President - Blue Spire
www.durandaljs.com

bitbonk

unread,
May 17, 2013, 7:35:20 AM5/17/13
to knock...@googlegroups.com, r...@bluespire.com
Sounds good. Less mental mapping, hurray ... ;)

I'd say that properties being functions have become our number one issue with knockout. It is just so easy to forget to put the braces.

rpn

unread,
May 20, 2013, 1:04:16 PM5/20/13
to knock...@googlegroups.com, r...@bluespire.com
Just FYI to anyone following this thread.  Steve Sanderson posted his implementation of this functionality here: http://blog.stevensanderson.com/2013/05/20/knockout-es5-a-plugin-to-simplify-your-syntax/.  Just a note to be careful with using this, if you are integrating with other KO plugins (custom bindings, etc.) as many would not be prepared to work with this style, as they specifically expect and check for observables/observableArrays.  Additionally, as you pass these properties around as arguments or set variables to their value, you will not retain the getter/setters that make the observability work, which can cause other issues with custom plugins.
Reply all
Reply to author
Forward
0 new messages