John Resigr的Simple JavaScript继承

作者: hopevow | 来源:发表于2017-02-06 15:51 被阅读7次

    在游戏引擎中使用继承


    (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运算符。

    相关文章

      网友评论

        本文标题:John Resigr的Simple JavaScript继承

        本文链接:https://www.haomeiwen.com/subject/bttsittx.html