Static

A static property or method is attached to the class it's self, rather than a class instance. Static members can only be referenced using the class name, and live in the defining class. To access the private/protected static scope, you must define the class by way of a function, which takes in the private static scope, and returns the object you would normally use to define a JOII class.

Example:

var MyClass = Class('MyClass', function (MyClassPrivateStaticScope) { return {
    'protected static string value': "",
    'public    static string public_value': "test",

    'public           nonStaticTest(string)': function(val) {
        MyClassPrivateStaticScope.setValue(val);
    },
    'public    static staticTest(string)': function(val) {
        MyClassPrivateStaticScope.setValue(val);
    },
    'public    static staticTest()': function() {
        return MyClassPrivateStaticScope.getValue();
    }
}});

MyClass.staticTest("first");
MyClass.staticTest(); // returns "first"

var mc = new MyClass();

// call the non-static function "nonStaticTest", which sets the protected static value
mc.nonStaticTest("second");

MyClass.staticTest(); // returns "second"

MyClass.getPublicValue(); // returns "test"

// throws an error, since the "value" property's visibility is protected
MyClass.getValue();

// throws an error, since the staticTest function is static, and not available on instances
mc.staticTest();

// throws an error, since the public_value property is static, and not available on instances
mc.getPublicValue();

In the above example, the private static scope was named "MyClassPrivateStaticScope" to make it more obvious what it was, but you can name the private static scope anything you wish. The recommendation is to name it the same as the external class name. The private scope name will "hide" the public scope, while providing a consistent naming scheme for both.

Example:

var MyClass = Class('MyClass', function (MyClass) { return {
    'protected static string value': "",

    'public    static test()': function() {

        // this is referencing the private static property "value" from the private scope, so this works fine
        return MyClass.getValue();
    }
}});

// MyClass is only accessing public scope at this point, so this would throw an error.
MyClass.getValue();

Inheritance

When inheriting static properties, the child class must work with them through their getter/setter functions.

Static properties live in the class they're defined in. This means that even when subclassing, you'll still be addressing the original property in the super class. This also means that all child classes share one copy of a super classes properties with that super class. The way this is implemented matches many other mainstream languages, such as C#.

Example:

var SuperClass = Class('SuperClass', function (SuperClass) { return {
    'protected static string value': ""
}});

var ChildClass1 = Class('ChildClass1', {'extends': SuperClass}, function (ChildClass1) { return {
    'public    static test()': function() {
        // this is referencing SuperClass.value
        return ChildClass1.getValue();
    }
}});

var ChildClass2 = Class('ChildClass2', {'extends': SuperClass}, function (ChildClass2) { return {
    'public    static test(string)': function(str) {
        // this is referencing SuperClass.value
        ChildClass2.setValue(str);
    }
}});

ChildClass2.test("new value");

// returns "new value", since both ChildClass1 and ChildClass2 share the same property from SuperClass
ChildClass1.test();

Static Classes

You can also denote an entire class as static, which will prevent it from being instantiated, or having any non-static members.

var MyClass = Class('MyClass', {'static': true}, function (MyClass) { return {
    'public    static test()': function() { },
    'public           test2()': function() { }, // throws an error, since it's not static
}});

var mc = new MyClass(); // throws an error, since you can't instantiate static classes