LoginSignup
59
58

More than 5 years have passed since last update.

クラス風継承を今どきの書き方でやってみる

Posted at

発端は自分が書いたブログ記事に対して、@hokacchaさんが今風の書き方ってことでReplyしてくれたのがきっかけです。
ベースというか、ほぼそれのコピペですが記事元ではやっていない処理が追加されていたり、実装していないものがあったりしたのでそれを追加・修正したものです。

'use strict'しても動きます。(翻訳記事元arguments.callee使ってるので、strictモードで動きません)

(function (win, doc, exports, undefined) {

    'use strict';

    var fnTest = /xyz/.test(function(){xyz;}) ? /\b_super\b/ : /.*/;

    function Class() { /* noop. */ }

    Class.extend = function (props) {

        var SuperClass = this;

        function Class() {
            if (typeof this.init === 'function') {
                this.init.apply(this, arguments);
            }
        }

        Class.prototype = Object.create(SuperClass.prototype, {
            constructor: {
                value: Class,
                writable: true,
                configurable: true
            }
        });

        Object.keys(props).forEach(function (key) {
            var prop   = props[key],
                _super = SuperClass.prototype[key],
                isMethodOverride = (typeof prop === 'function' && typeof _super === 'function' && fnTest.test(prop));

            if (isMethodOverride) {
                Class.prototype[key] = function () {
                    var ret,
                        tmp = this._super;

                    Object.defineProperty(this, '_super', {
                        value: _super,
                        configurable: true
                    });

                    ret = prop.apply(this, arguments);

                    Object.defineProperty(this, '_super', {
                        value: tmp,
                        configurable: true
                    });

                    return ret;
                };
            }
            else {
                Class.prototype[key] = prop;
            }
        });

        Class.extend = SuperClass.extend;

        return Class;
    };

    exports.Class = Class;
}(window, window.document, window));

使い方はこんな感じ。

(function (win, doc, exports, undefined) {

    'use strict';

    var Person = Class.extend({
        init: function () {
            console.log('hoge');
        }
    });

    var Ninja = Person.extend({
        init: function () {
            this._super();
            console.log('foo');
        }
    });

    var Samurai = Ninja.extend({
        init: function () {
            this._super();
            console.log('bar');
        },
        _super: 'super!'
    });

    var p = new Person();
    var n = new Ninja();
    var s = new Samurai();

    console.log(s._super);

}(window, window.document, window));
59
58
5

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
59
58