FWIW, here is the pattern that appears to work in JSFiddle for a "static var 
foo":

o.get__foo = function() {
   var value = <initializer expression>
   Object.defineProperty(o, 'foo', {value : value, writable: true});
   return value;
}
o.set__foo = function(value) {
    Object.defineProperty(o, 'foo', {value : value, writable: true});
}
Object.defineProperties(o, { foo: { get: o.get__foo,set: o.set__foo, 
configurable: true}})

We have to use Object.defineProperties in order to use an @lends JSDoc 
annotation (not shown) for the minifier.

A similar pattern will be used for "static const foo":

o.get__foo = function() {
   var value = <initializer expression>
   Object.defineProperty(o, 'foo', {value : value, writable: false});
   return value;
}
Object.defineProperties(o, { foo: { get: o.get__foo, configurable: true}})

Of course, I could be wrong...

-Alex

On 11/5/19, 8:56 AM, "Harbs" <[email protected]> wrote:

    Good point on PAYG.
    
    If we use #2 with one-time lazy evaluation, I think that’s the best of both 
worlds.
    
    Thanks,
    Harbs
    
    > On Nov 5, 2019, at 6:44 PM, Alex Harui <[email protected]> wrote:
    > 
    > Yeah, in my local branch I'm playing with various ways to not run the 
initializer more than once.  We can tweak the pattern later.  It involves 
re-defining the property, but isn't  quite the patterns offered below.
    > 
    > IMO, #2 is more PAYG than #1.  In #1, all initializers run regardless of 
whether your code uses that value or not.  In #2, the initializers run on 
demand, which is actually somewhat more like the Flash runtime.  AIUI, Flash 
does not run a class's static initializers until the class is about to be 
accessed by code.  All initializers for a class then run, but if your code 
never gets to the point where the verifier needs to verify the class, the 
initializers are not run.
    > 
    > -Alex
    > 
    > On 11/4/19, 11:49 PM, "Greg Dove" <[email protected]> wrote:
    > 
    >    Yeah, in all cases where I had to do this manually I used a private 
static
    >    backing var and populated it on first request similar to what is 
typically
    >    done for singleton-like get accessors. Otherwise it's not really safe
    >    compared to the original (and as you say, could have performance issues
    >    too).
    > 
    >    On Tue, 5 Nov 2019, 20:31 Harbs, <[email protected]> wrote:
    > 
    >> It seems to me that the getter approach can have an impact on 
performance.
    >> With approach #1, the static consts will only be evaluated once, while 
with
    >> #2, it will be evaluated every time it’s accessed.
    >> 
    >> Maybe we could use a hybrid approach where “bar” is redefined as the
    >> evaluated value the first time it’s accessed.
    >> 
    >> Something like this:
    >> 
    >> Foo.get__bar = function() {
    >>  var val = ResourceManager.getInstance().getString("baz");
    >>  delete Foo.bar;
    >>  Foo.bar = val;
    >>  return val;
    >> Object.defineProperty(Foo, "bar", {get: Foo.get__bar});
    >> 
    >> or maybe this:
    >> 
    >> Foo.get__bar = function() {
    >>  var val = ResourceManager.getInstance().getString("baz");
    >>  // is delete needed?
    >>  delete Foo.bar;
    >>  Object.defineProperty(Foo, "bar", {get: function(){return val}});
    >>  return val;
    >> }
    >> Object.defineProperty(Foo, "bar", {get: Foo.get__bar});
    >> 
    >> 
    >> Harbs
    >> 
    >>> On Nov 5, 2019, at 2:52 AM, Alex Harui <[email protected]> wrote:
    >>> 
    >>> Hi,
    >>> 
    >>> The issue of complex static initializers and dependency order keeps
    >> coming up.  In reviewing the past discussions, there were a couple of
    >> suggestions:
    >>> 1) separate static initializers into a block of code that runs after the
    >> class is defined
    >>> 2) use getters
    >>> 
    >>> I'm going to try #2.  I'm not convinced #1 will work well with minifiers
    >> or help us get the dependency order right.
    >>> 
    >>> Thoughts?  Is there a case where getters won't work?
    >>> 
    >>> For:
    >>> 
    >>> public class Foo {
    >>> public static const bar:String =
    >> ResourceManager.getInstance().getString("baz");
    >>> }
    >>> 
    >>> We currently generate:
    >>> 
    >>> Foo.bar = ResourceManager.getInstance().getString("baz");
    >>> 
    >>> And lots of other code tries to understand that the
    >> goog.require("ResourceManager") is more important than other 
goog.requires
    >> in the remove-circulars dependency calculation.
    >>> 
    >>> But if we generate:
    >>> Foo.get__bar = function() { return
    >> ResourceManager.getInstance().getString("baz");};
    >>> Object.defineProperty(Foo, "bar", {get: Foo.get__bar});
    >>> 
    >>> Then I think no statics will get evaluated at load time.
    >>> 
    >>> Of course, I could be wrong...
    >>> -Alex
    >>> 
    >> 
    >> 
    > 
    > 
    
    

Reply via email to