locked
Are javascript getter / setter supported with WinJS? RRS feed

  • Question

  • I have a strange behavior when using the WinJS.Class.define. My getter is being invoked before the object constructor is invoked and therefore I don't get the expected value when calling the property.  Here is a code sample of a working getter in pure javascript, followed by the code I'm using with the WinJS.Class.define .

    (function () {
        "use strict";
    
        // Sample in pure javascript
        var basicBaseClass = function (){
            this._a = 1;
            this._b = 2;
        };
        basicBaseClass.prototype = {
            get sum() {
                return this._a + this._b;
            },
        };
        var willBe3 = new basicBaseClass().sum;
        
        // Sample with WinJS.Class.define
        var baseClass = WinJS.Class.define(
            function () {
                this._a = 1;
                this._b = 2;
            }, {
                get sum() {
                    // Invoked before the ctor
                    return this._a + this._b;
                },
            });
        
        var resultIsNaN = new baseClass().sum;
    })();

    So is it only a bug, or is it out of scope to support getter / setter this way?

    I'm using VS2012 RC on Windows 8 Release Preview.

    • Edited by Instriker Wednesday, June 6, 2012 4:30 PM More info on environment.
    Wednesday, June 6, 2012 4:26 PM

Answers

  • You just have the syntax wrong. The property is an object of that name with its nested members being functions called set and get.

    // Sample with WinJS.Class.define
    var baseClass = WinJS.Class.define(
        function () {
            this._a = 1;
            this._b = 2;
        }, {
            sum: {
                get: function (){
                    // Invoked before the ctor
                    return this._a + this._b;
                },
                set: function (value) {
                    throw new error("Not Supported");
                }
            }
        });
    
    var sum = new baseClass().sum;


    • Proposed as answer by Bryan Thomas Wednesday, June 6, 2012 8:00 PM
    • Edited by Bryan Thomas Wednesday, June 6, 2012 8:01 PM
    • Marked as answer by Instriker Wednesday, June 6, 2012 8:16 PM
    Wednesday, June 6, 2012 7:59 PM
  • Hi Instriker,

    Your syntax was close, but slightly off:

    var Foo = WinJS.Class.define(function () {
        this.a = 1;
        this.b = 2;
    },
    {
        sum: { get: function() { return this.a + this.b; }}
    });

    The second argument to WinJS.Class is an object containing property descriptions. These can just be simple values (functions, numbers, strings) or they can be ES5 property descriptors.  Some more documentation on property descriptors here: http://msdn.microsoft.com/en-us/library/dd548687(v=vs.94).aspx

    The nice thing is that WinJS fills in some default values for you, such as enumerable is set to true unless your property name starts with an underscore.

    Cheers,

    -Jeff

    Wednesday, June 6, 2012 8:07 PM

All replies

  • You just have the syntax wrong. The property is an object of that name with its nested members being functions called set and get.

    // Sample with WinJS.Class.define
    var baseClass = WinJS.Class.define(
        function () {
            this._a = 1;
            this._b = 2;
        }, {
            sum: {
                get: function (){
                    // Invoked before the ctor
                    return this._a + this._b;
                },
                set: function (value) {
                    throw new error("Not Supported");
                }
            }
        });
    
    var sum = new baseClass().sum;


    • Proposed as answer by Bryan Thomas Wednesday, June 6, 2012 8:00 PM
    • Edited by Bryan Thomas Wednesday, June 6, 2012 8:01 PM
    • Marked as answer by Instriker Wednesday, June 6, 2012 8:16 PM
    Wednesday, June 6, 2012 7:59 PM
  • Hi Instriker,

    Your syntax was close, but slightly off:

    var Foo = WinJS.Class.define(function () {
        this.a = 1;
        this.b = 2;
    },
    {
        sum: { get: function() { return this.a + this.b; }}
    });

    The second argument to WinJS.Class is an object containing property descriptions. These can just be simple values (functions, numbers, strings) or they can be ES5 property descriptors.  Some more documentation on property descriptors here: http://msdn.microsoft.com/en-us/library/dd548687(v=vs.94).aspx

    The nice thing is that WinJS fills in some default values for you, such as enumerable is set to true unless your property name starts with an underscore.

    Cheers,

    -Jeff

    Wednesday, June 6, 2012 8:07 PM
  • Ok thanks, it works with this syntax, so I'll use it. I was asking because the previous syntax is also possible and a little shorter to write. For exemple, there is info on it on http://javascriptweblog.wordpress.com/2010/11/15/extending-objects-with-javascript-getters/ .
    Wednesday, June 6, 2012 8:16 PM
  • Ah, yes I see what you mean. So you are correct that for object literals you can specify a getter and a setter using the syntax you gave. The problem is that WinJS internally iterates over all of the properties in the instanceMember object, so when it processes your "sum" property it ends up evaluating the getter (which returns NaN) and then WinJS happily assumes you meant to set a literal NaN as the value of "sum" and so does a defineProperty with that.

    I suppose in a perfect world WinJS would be clever enough to do a getOwnPropertyDescriptor on the argument so it could avoid getting into this trouble. Seems like WinJS.Class.mix suffers from the same issue. I think the team has discussed this before, but I'll revisit it with them. Thanks for your feedback!

    Cheers,

    -Jeff


    Wednesday, June 6, 2012 9:10 PM