mcaz
6/3/2019 - 8:17 AM

js: define class

function Sample() {}

Sample.prototype.showName = function() {
  console.log('Sample');
}

new Sample().showName();
function Sample() {}

Sample.prototype = {
  showName: function() {
    console.log('Sample');
  }
}

new Sample().showName();
function Sample() {
  this.showName = function() {
    console.log('Sample');
  };
}

new Sample().showName();
function Sample() {
  return {
    showName: function() {
      console.log('Sample');
    }
  }
}

new Sample().showName();
/** GlobalRegistor CLASS */ (function (modules) {

    // GlobalRegistor class's work space.

    "use strict";

    var properties = {};

    // constructor

    function GlobalRegistor () {}

    // static accessor

    Object.defineProperty(GlobalRegistor, 'global', {
        /**
         * @return {Object} global object
         */
        get: function() {
            return new Function('return this')();
        }
    });

    Object.defineProperty(GlobalRegistor, 'properties', {
        /**
         * @return {Object} registed properties
         */
        get: function() {
            return properties;
        }
    });

    // static method

    Object.defineProperty(GlobalRegistor, 'readOnly', { writable: false,
        /**
         * @param  {String} name
         * @param  {Any}    value
         * @return {Void}
         * @example
         * --- success pettern ---
         * GlobalRegistor.readOnly('globalModules', {});
         * window.globalModules.fn  = function () { console.log('success!'); };
         * window.globalModules     = null;
         * window.globalModules.fn(); // success!
         * widnow.globalModules.foo = 1;
         * widnow.globalModules.foo = 2;
         * console.log(window.globalModules.foo) // 2
         * --- faital pettern ---
         * window.globalModules    = {};
         * window.globalModules.fn = function () { console.log('success!'); };
         * window.globalModules    = null;
         * window.globalModules.fn(); // Uncaught TypeError: fn is not a function
         */
        value: (function readOnly (name, value) {
            if (GlobalRegistor.exist(name)) {
                throw new Error(name + ' is Declare Property');
            } else {
                Object.defineProperty(GlobalRegistor.global, name, { writable: false,
                    value: properties[name] = value
                });
            }
        })
    });

    Object.defineProperty(GlobalRegistor, 'exist', { writable: false,
        /**
         * @param {String} name
         */
        value: function (name) {
            return GlobalRegistor.global[name] !== void 0;
        }
    })

    // Define GlobalRegistor class to global object.

    GlobalRegistor.readOnly('GlobalRegistor', GlobalRegistor);

})(Object.freeze({ /** export modules to GlobalRegistor class's work space. */ }));

var ClassHelper = /** CLASS */ (function (modules) {

    // ClassHelper class's work space.

    "use strict";

    // constructor

    function ClassHelper () {}

    // static accessor

    Object.defineProperty(ClassHelper, 'CLASS_NAME', {
        /**
         * @return {String}
         */
        get: function CLASS_NAME () {
            return 'ClassHelper';
        }
    });

    // public static const

    Object.defineProperty(ClassHelper, 'getClassName', {

        writable: false,

        /**
         * @method
         * @param  {Any} v
         * @return {String}
         */
        value: (function getClassName (v) {
            return v.constructor.name;
        })
    });

    Object.defineProperty(ClassHelper, 'extendsClass', {

        writable: false,

        /**
         * @param  {Class} Sub    sub class
         * @param  {Class} Parent parent class
         * @return {Class} parent class
         */
        value: (function extendsClass (Sub, Parent) {
            Sub.prototype = Object.create(Parent.prototype);
            Sub.prototype.constructor = Sub;
            return Parent;
        })
    });

    return ClassHelper;

})(Object.freeze({ /** export modules to ClassHelper class's work space. */ }));

var DomHelper = /** CLASS */  (function () {

    // DomHelper class's work space.

    "use strict";

    // constructor

    function DomHelper () {}

    // public static const

    Object.defineProperty(DomHelper, 'getClassName', {

        writable: false,

        /**
         * @param  {String} src
         * @param  {Object} props
         * @return {String}
         * @example
         * Domhelper.template(`
         *   <div id="{{param1}}" class="{{param2}}" value="{{param2}}">
         *     {{param3}}
         *   </div>`,
         *   {
         *     param1: 'app',
         *     param2: 'is-active',
         *     param3: 'キー名に制限はない、src内に複数の同名キーがある場合は再帰的に置き換える'
         *   }
         * );
         * => `
         *   <div id="app" class="is-active" value="is-active">
         *     キー名に制限はない、src内に複数の同名キーがある場合は再帰的に置き換える
         *   </div>`
         * @example
         * DomHelpers.templates('置き換え対象がない場合は何もしない{{foo}}', { bar: 'bar' });
         * => `置き換え対象がない場合は何もしない{{foo}}'
         */
        value: (function getClassName (src, props) {
            return Object.keys(props).reduce(function (acc, cur) {
                return (acc = acc === '' ? src : acc).replace(new RegExp('\{\{' + cur + '\}\}', 'g'), props[cur]);
            }, '');
        })
    });

    return DomHelper;

})(Object.freeze({ /** export modules to DomHelper class's work space. */ }));

var Parent = /** CLASS */ (function (modules) {

    // Parent class's work space.

    "use strict";

    // constructor

    function Parent (props) {
        this.props = props;
        console.log('Parent __constructor');
    }

    // public value

    /**
     * Show class's name
     * @return {Void}
     */
    Parent.prototype.showName = function () {
        console.log('Parent');
    }

    // Object.defineProperty(Parent.prototype, 'showName', { writable: false,
    //     /**
    //      * Show class's name
    //      * @return {Void}
    //      */
    //     value: (function showName () {
    //         console.log('Parent');
    //     })
    // });

    // accessor

    Object.defineProperty(Parent.prototype, 'props', {
        /**
         * props setter
         * @param  {Any} props
         * @return {Void}
         */
        set: function (props) {
            this._props = Sub.Options(props);
        },
        /**
         * props getter
         * @return {Object} this._props
         */
        get: function () {
            return 'Parent props';
        }
    });

    return Parent;

})(Object.freeze({ /** export modules to Parent class's work space. */ }));

var SubOptions = /** CLASS */ (function (modules) {

    // SubOptions class's work space.

    "use strict";

    // constructor

    /**
     * class options
     * @param  {Object} props
     * @prop   {Any}    props.a
     * @prop   {Any}    props.b
     * @prop   {Any}    props.c
     * @return {Object}
     */
    function SubOptions (props) {
        return {
            a: props.a || 'a',
            b: props.b || 'b',
            c: props.c || 'c'
        }
    }

    return SubOptions;

})(Object.freeze({ /** export modules to SubOptions class's work space. */ }));

var Sub = /** CLASS */ (function (modules) { const __super__ = ClassHelper.extendsClass(Sub, Parent)

    // Sub class's work space.

    "use strict";

    // constructor

    /**
     * @param {SubOptions|Object} props
     */
    function Sub(props) {
        __super__.call(this, props);
        // this.props = props;
    }

    // public static const

    Object.defineProperty(Sub, 'Options', {

        writable: false,

        /**
         * @param  {Object} props
         * @return {SubOptions}
         */
        value: (function Options (props) {
            return ClassHelper.getClassName(props) === 'SubOptions'
                ? props
                : new SubOptions(props);
        })
    });

    Object.defineProperty(Sub, 'create', {

        writable: false,

        /**
         * Create Sub class's instance from Sub props list
         * @param  {Array<SubOptions>} list
         * @return {Array<Sub>}
         */
        value: (function create (list) {
            return [].concat([], list).map(function (props) {
                return Sub.Options(props);
            });
        })
    });

    // public value

    /**
     * @return {Void}
     */
    Sub.prototype.showClassName = function () {
        console.log('Sub');
    }

    // public const

    Object.defineProperty(Sub.prototype, 'getClassName', {

        writable: false,

        /**
         * @return {String}
         */
        value: (function getClassName () {
            return this.constructor.name;
        })
    });

    Object.defineProperty(Sub.prototype, 'showName', {

        writable: false,

        /**
         * Show class's name
         * @return {Void}
         */
        value: (function showName () {
            console.log('Sub');
        })
    });

    // accessor
    // Override if alliance property exists in Super class

    Object.defineProperty(Sub.prototype, 'props', {
        /**
         * props setter
         * @param  {Any} props
         * @return {Void}
         */
        set: function (props) {
            this._props = Sub.Options(props);
        },
        /**
         * props getter
         * @return {Object} this._props
         */
        get: function () {
            return 'Sub props';
        }
    });

    return Sub;

})(Object.freeze({ /** export modules to Sub class's work space. */

    /**
     * @return {Void}
     */
    test1: function () {
        this.test2();
    },

    /**
     * @param  {Any} e
     * @return {Void}
     */
    test2: function (e) {
        console.log('test2');
    },
}));

// mout
(function (target, modules) {
    !GlobalRegistor.exist(target) && GlobalRegistor.readOnly(target, {})

    Object.keys(modules).forEach(function (name) {
        myModules[name] = modules[name]
    });
})('myModules', {
    ClassHelper: ClassHelper,
    DomHelper  : DomHelper,
    Parent     : Parent,
    SubOptions : SubOptions,
    Sub        : Sub
});

var sub = new Sub(new SubOptions({
    a: 0, b: void 0, c: false
}));

var sub = new Sub({ a: 0, b: void 0, c: false });

var subs = Sub.create([
    { a: 0, b: void 0, c: false },
    { a: 0, b: void 0, c: false },
    { a: 0, b: void 0, c: false },
    new SubOptions({ a: 0, b: void 0, c: false }),
    new SubOptions({ a: 0, b: void 0, c: false })
]);

sub.showName();
sub.showClassName();

console.log('sub', sub);
console.log('subs', subs);
console.log('sub.name', sub.getClassName());
console.log('sub.props', sub.props);

sub.props = 10;

console.log('sub.props', sub.props);

GlobalRegistor.readOnly('test', 'a');

test = 'foo';

console.log('test', test);
class Sample {
  showName() {
    console.log('Sample');
  }
}

new Sample().showName();