web编程之路程序猿阵线联盟-汇总各类技术干货

John Resigr的Simple JavaScript继承

2017-02-06  本文已影响7人  hopevow

在游戏引擎中使用继承


(function(){
    var initializing = false,
        fnTest = /xyz/.test(function(){xyz;}) ? /\b_super\b/ : /.*/;
    this.Class = function(){};
    Class.extend = function(prop) {
        var _super = this.prototype;
        initializing = true;
        var prototype = new this();
        initializing = false;

        for (var name in prop) {
            prototype[name] = typeof prop[name] == "function" && typeof _super[name] == "function" && fnTest.test(prop[name]) ? (function (name, fn) {
                return function() {
                    var tmp = this._super;
                    this._super = _super[name];
                    var ret = fn.apply(this, arguments);
                    this._super = tmp;
                    return ret;
                };
            })(name, prop[name]) : prop[name];
        }

        function Class() {
            if (!initializing && this.init) {
                this.init.apply(this, arguments);
            }
        }

        Class.prototype = prototype;

        Class.prototype.constructor = Class;
        Class.extend = arguments.callee;
        return Class;
    };

})();

这段代码的主旨是允许使用extend方法从现有类中派生出新类,继承得来的对象可像父对象那样共享相同的实例方法,可以通过子方法this._super()调用父方法。这一特殊情况由代码中部的循环进行处理,该循环并非仅是一味的拷贝整个方法,它会检查父类的现有方法,然后创建一个包装器函数,在调用期间,该函数临时将this.super方法设置成父类的定义
for (var name in prop) { prototype[name] = typeof prop[name] == "function" && typeof _super[name] == "function" && fnTest.test(prop[name]) ? (function (name, fn) { return function() { var tmp = this._super; this._super = _super[name]; var ret = fn.apply(this, arguments); this._super = tmp; return ret; }; })
上述代码检查属性是否已存在于超类中,若是,则创建一个函数,在再次调用新方法之前,该函数会先对this._super执行一个临时赋值,若该方法不存在,代码仅对属性赋值,不会加入任何额外开销。
Class 代码还加入了一个构造函数,该函数自动调用对象的init()方法,还支持初始化函数的链式调用
function Class() { if (!initializing && this.init) this.init.apply(this, arguments); }
最后把extend方法添加到类中,这样类就可以进一步子类化:
Class.extend = arguments.callee;
调用arguments.calle时,会返回被调用的方法(在该例中是extend),然后把方赋给所返回的Class对象的属性extend,以此来支持进一步的子类化。

运用Class的功能

var Person = Class.extend({
  init: function(){console.log('created person');},
  speak: function(){console.log('person speaking');}
});
var p = new Person();
p.speak();

var Guy = Person.extend({
  init: function(){this._super();console.log('created guy');},
  speak: function(){this._super();console.log('i am a guy');}
});
var bob = new Guy();
bob.speak();
var Girl = Person.extend({
  init: function(){console.log('created girl');},
  speak: function(){console.log('i am a girl');}
});
var jill = new Girl();
jill.speak();

类功能使得以一种清晰的方式创建并扩展类成为可能,这些子类确保超类的方法能在适当的时候被调用。
bob instanceof Person //true bob instanceof Guy //true bob instanceof Girl //false jill instanceof Person //true jill instanceof Guy //false jill instanceof Girl //true
该功能也简化了必要时对于对象类型的使用,可以注意到,bob和jill都如预期般响应了instanceof运算符。

上一篇下一篇

猜你喜欢

热点阅读