Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

using static variables to initialize variables in the same class

I am trying to emulate this following behavior of Java with Javascript using mootools/Dojo. A instance variable that needs to be initialized with a class static variable value.

Class xyz {
    public static static_constants {
        TEST_CONST1 : "abc";
    }

    private a = static_constants.TEST_CONST1;
}

I can do it the way below, but then com.example.test.static_constants.TEST_CONST1 will not exist anymore as we have overwritten com.example.test. But if com.example.test.static_constants.TEST_CONST1 is not defined earlier, the assignment with-in the class will fail.

com.example.test.static_constants.TEST_CONST1 = "abc";

var com.example.test = new Class ({
    a : com.example.test.static_constants.TEST_CONST1
});

Two workarounds that work:

(I) - have separate instance variable inside the class; and use static outside

var com.example.test = new Class ({
    static_constants : {
        TEST_CONST1 : "abc"
    },
    a : this.static_constants.TEST_CONST1
});

com.example.test.static_constants.TEST_CONST1 = "abc";

(II) recreate the static after class is defined

com.example.test.static_constants.TEST_CONST1 = "abc";

var com.example.test = new Class ({
    a : com.example.test.static_constants.TEST_CONST1
});

com.example.test.static_constants.TEST_CONST1 = "abc";

What am I missing? Both these ways don't seem clean to me. There must be a cleaner way to do this (without using extend etc - which will further break the class).

like image 897
v2b Avatar asked Nov 19 '25 11:11

v2b


2 Answers

May I interject and stop you right there.

JavaScript is not JAVA. The fact that you need to not use JAVA now does not mean you need to move the crap associated with namespaces and statics and patterns that it has over to JavaScript. JavaScript has different patterns when it comes to doing things.

In any case, since you did not ask what the best pattern for organising stuff and Classes in MooTools are and you just want to know how to mutate and extend your existing object, you can do this small factory:

http://jsfiddle.net/vrKX2/4/

var com = {
    example: {
        test: {
            static_constants: {
                TEST_CONST1: "abc"
            }
        }
    }
};

Class.extend({
    fromExisting: function(namespace, constructorObject){
        return Object.append(new this(constructorObject), namespace);
    }
});

// this is non-DRY. It kind of is Object.merge()
com.example.test = Class.fromExisting(com.example.test, {

    a: com.example.test.static_constants.TEST_CONST1,
    initialize: function(){
        console.warn(this.a);
    },
    getStatic: function(what){
        return com.example.test.static_constants[what];
    }
});

var t = new com.example.test();
console.log(Object.getOwnPropertyNames(t)); // no static_constants
console.log(t.a);
console.log(com.example.test.static_constants);
com.example.test.static_constants.TEST_CONST1 = 'bbb';
console.log(t.a);
console.log(t.getStatic('TEST_CONST1'));

Class.fromExisting will accept some object, which it will merge its properties against the class constructor object (but static, not on the prototype) - but it cannot mutate the obj it is extending in the constructor (can't think of why right now but it's saturday night).

you really ought to just implement a more sensible module naming approach / namespacing - like in AMD and use constants on a separate config object. there is no need to mix the two namespaces - or indeed, the need to namespace at all when you use AMD (though you can name your modules).

Please don't use this factory pattern, just shows how flexible mootools can be when extending types etc.

Instead, you can simply do - as mentioned - just Object.merge()

com.example.test = Object.merge(new Class({
    a: com.example.test.static_constants.TEST_CONST1,
    initialize: function(){
        console.warn(this.a);
    },
    getStatic: function(what){
        return com.example.test.static_constants[what];
    }
}), com.example.test);

since you are working with some dodgy namespaces, you want to look at extending Object Type (not the prototype of Object) with get/set that work deep, Daniel Buchner tried to land it but was shot down.

https://github.com/mootools/mootools-core/pull/2191/files

these may take away the pain of creating deeper namespaces from dotted strings. have fun now.

like image 90
Dimitar Christoff Avatar answered Nov 21 '25 00:11

Dimitar Christoff


If you're using AMD, you would define a module without creating a global object chain like com.example.test. The documentation for declare has a short section on static objects, but the concept is straightforward: you can hang "extras" off of the module you return.

If you need a constant that's only available to the module it is defined in, just use a regular variable. If you need access to it outside of the module, just hang it off the module object that you return. This is similar to the first method in your question, but there's no need to involve an ugly chain of global objects.

like image 44
Thomas Upton Avatar answered Nov 21 '25 01:11

Thomas Upton



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!