ANTON072
3/16/2013 - 5:00 AM

class_extend.js

// http://ejohn.org/blog/simple-javascript-inheritance/

function Class() {}

Class.extend = function extend(props) {
  var SuperClass = this;

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

    // _superプロパティを書き込み禁止にする
    Object.defineProperty(this, '_super', {
      value: undefined,
      enumerable: false,
      writable: false,
      configurable: true
    });
  }

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

  // set instance method
  Object.keys(props).forEach(function(key) {
    var prop = props[key];
    var _super = SuperClass.prototype[key];
    var isMethodOverride =
      typeof prop === 'function' && typeof _super === 'function';

    if (isMethodOverride) {
      Class.prototype[key] = function() {
        // _superプロパティを設定
        Object.defineProperty(this, '_super', {
          value: _super,
          enumerable: false,
          writable: false,
          configurable: true
        });

        var ret = prop.apply(this, arguments);

        // _superプロパティを書き込み禁止にする
        Object.defineProperty(this, '_super', {
          value: undefined,
          enumerable: false,
          writable: false,
          configurable: true
        });

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

  // set class method
  Object.keys(SuperClass).forEach(function(key) {
    Class[key] = SuperClass[key];
  });

  return Class;
};

//------------------------------

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

var Ninja = Person.extend({
  init: function(){  
    this._super( false );  
  },
  hoge: function() {
    console.log('fuga');
    this._super();
  }
});  
  
var p = new Person(true);  
console.log(p.dancing); // => true  
  
var n = new Ninja();  
console.log(n.dancing); // => false  

n.hoge(); //=> fuga hoge

console.log(n.constructor === Ninja); // => true