Has there been any work to support js properties in Ember?


#1

One of my biggest annoyances with ember is .get, .set central. I understand there is some sort of plan to move to ECMAScript proxies later on to resolve this.

At Discourse we don’t need to support IE8 so I was thinking why not just meta program the properties so we can avoid the need for .get and .set , getters and setters are everywhere we really care about http://kangax.github.io/es5-compat-table/

The trivial, inefficient solution is:

window.Foo = Ember.Object.extend({
  init: function(){
    var me, prop, i;
    this._super();
    me = this;
    if (this.properties && this.properties.length) {
      for(i=0; i<this.properties.length; i++) {
        prop = this.properties[i];
        Object.defineProperty(me, prop, {
          set: function(val){ 
            Ember.propertyWillChange(me, prop, val); 
            this["__" + prop] = val;
            Ember.propertyDidChange(me, prop, val); 
          },
          get: function(){ return this.get("__" + prop); }
        });
      }
    }
  }
});

window.Bar = Foo.extend({
  properties: ["baz"],
  
  yay: function(){
    console.log("baz: " + this.baz);
  }.observes("baz")
});



var b = Bar.create();
b.baz = 10;
// "baz: 10"

Even this very rough cut is not way worse that the current state: http://jsperf.com/ember-auto-prop once the getter / setter is bolted to the prototype it will be way faster.

Additionally, computed properties need some extra magic, but it all feels feasible.


Has anyone thought about this problem / solution, should this be a switch in Ember ?


#2

Ember appears to use Object.defineProperty extensively and in many cases value = this.prop; can be substituted for value = this.get('prop'); Comments in the code also give the impression that this is expected:

On all newer browsers, you only need to use this method [Ember.get] to retrieve properties if the property might not be defined on the object and you want to respect the unknownProperty handler. Otherwise you can ignore this method.

But my experience has been that it’s unpredictable: computed properties never work with simple obj.prop getter syntax and since one can always extend an object and replace a native object property with a computed version pretty much anything could be a computed property.

Is there any documentation on this feature? Anything about Ember.ENV.MANDATORY_SETTER?


#3

This actually was how computed properties were initially implemented. However, we had to remove the feature because it was too unreliable when it came to ObjectControllers and other ObjectProxies.

The bottom line is that too much behavior in Ember relies on unknownProperty. The good news is that we will soon be able to use ES6’s proxies to achieve the same goal.


#4

I think that a very important lesson though is the staggering perf improvement that can be achieved by using properties, besides code being significantly more readable. Of course I agree this test is not doing everything get/set does, however it is an indicator. Also, I think it does call out the uniform access principle, we should be a bit more careful applying it around perf critical areas.

http://jsperf.com/ember-get-set

Really hoping for a htmlbars style push to redesigning so properties can be used, it would allow us to only bolt on properties where needed, leading to a massive perf gain.

cc @wycats @eviltrout @ebryn