作为 jquery 的作者. John Resig 在博客里记录了一种 class 的实现, 原文在此
下面是源码:
- (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;
- };
- })();
我们把调用方法带入进去看看其到底是怎么实现的.
- var Person = Class.extend({
- init: function(isDancing){
- this.dancing = isDancing;
- },
- dance: function(){
- return this.dancing;
- }
- });
因此
- prop = {
- init: function(isDancing){
- this.dancing = isDancing;
- },
- dance: function(){
- return this.dancing;
- }
- }
var _super = 超级父类的原型对象
var prototype = 由超级父类生成的实例
- initializing = false;
** 第一次 for 循环 **
- typeof prop["init"] == "function" // true
- typeof _super["init"] == "function" // false
- typeof fnTest.test(function(isDancing){this.dancing = isDancing;}) // false
** 循环结束后, 所以 **
- prototype["init"] = prop["init"];
- prototype["dance"] = prop["dance"]
子类:
- function Class(){
- if(!initializing && this.init){
- this.init.apply(this, arguments);
- }
- }
- // 赋值原型链, 完成继承
- Class.prototype = prototype;
- // 改变 constructor 的指向
- Class.prototype.constructor = Class;
- // 为子类 Class 添加 extend 方法
- Class.extend = arguments.callee;
- // 返回子类
- return Class;
因此
Person = 返回的子类 Class;
而子类 Class
此时的 this 指向超级父类 Class
- function Class(){
- if(!initializing && this.init){
- this.init.apply(this, arguments);
- }
- }
- Class.prototype = {
constructor: 指向自身的构造函数 Class
- init: function(isDancing){this.dancing = isDancing},
- dance: function(){ return this.dancing;}
- }
Class.extend 方法与超级父类相同
调用, 使用 Person 构造函数, 创建一个实例.
- var p = new Person(true);
当 new Person() 时, 实际上调用的是 返回的子类 Class
此时 this 指向刚刚创建生成的实例 p,
因此 if 条件为真, 执行 this.init.apply(this,arguments)
- init: function(true){this.dancing = true;}
此时调用 p.dance(); 则其输出为 true
此时, Person 类指向子类 Class
- function Class(){
- if(!initializing && this.init){
- this.init.apply(this, arguments);
- }
- }
- Class.prototype = {
constructor: 指向自身的构造函数 Class
- init: function(isDancing){this.dancing = isDancing},
- dance: function(){ return this.dancing;}
- }
Class.extend 方法与超级父类相同
当基于 Person 进行继承时
- var QdGithub = Person.extend({
- init: function(){
- this._super( false );
- },
- dance: function(){
- // Call the inherited version of dance()
- return this._super();
- },
- swingSword: function(){
- return true;
- }
- });
因此
var _super = Person 的原型对象
var prototype = Person 类生成的实例
- initializing = false;
** 第一次 for 循环:**
- typeof prop["init"] == "function" // true
- typeof _super["init"] == "function" // true
- fnTest.test(function(){this._super(false)}) // true
因此进入闭包, 把 Person 类的对象属性方法混入子类上.
参数:
- name: "init"
- fn: function(){this._super(false)}
返回匿名函数
- prototype["init"] = function(){
- var tmp = this._super;
- this._super = function(isDancing){this.dancing = isDancing;};
- fn = function(){this._super(false)};
- var ret = fn.apply(this, arguments);
- this._super = tmp;
- return ret;
- }
第二次循环同第一次循环
- prototype["dance"] = function(){
- var tmp = this._super;
- this._super = function(){ return this.dancing;}
- fn = function(){return this._super();}
- var ret = fn.apply(this, arguments);
- this._super = tmp;
- return ret;
- }
第三次循环
- prototype["swingSword"] = function(){return true;}
返回子类
- function Class(){
- if(!initializing && this.init){
- this.init.apply(this, arguments);
- }
- }
- Class.prototype = {
constructor: 指向自身的构造函数 Class
- init: function(){
- var tmp = this._super;
- this._super = function(isDancing){this.dancing = isDancing;};
- fn = function(){this._super(false)};
- var ret = fn.apply(this, arguments);
- this._super = tmp;
- return ret;
- },
- dance: function(){
- var tmp = this._super;
- this._super = function(){ return this.dancing;}
- fn = function(){return this._super();}
- var ret = fn.apply(this, arguments);
- this._super = tmp;
- return ret;
- },
- swingSword: function(){return true;}
- }
Class.extend 方法与超级父类相同
因此: QdGithub = 返回的子类 Class(就是上面刚刚分析, 返回的子类 Class)
调用, 使用 QdGithub 构造函数, 创建一个实例.
- var n = new QdGithub(true);
当 new QdGithub() 时, 实际上调用的是 返回的子类 Class
此时 this 指向刚刚创建生成的实例 n,
因此 if 条件为真, 执行 this.init.apply(this,arguments), 把实例 n 的 dancing 属性设置为 false
- init: function(){
- var tmp = this._super;
- this._super = function(isDancing){this.dancing = isDancing;};
- fn = function(){this._super(false)};
- var ret = fn.apply(this, arguments);
- this._super = tmp;
- return ret;
- }
此时调用 n.dance(); 则其输出为 false
此时调用 n.swingSword(); 则其输出为 true
- // Should all be true
- p instanceof Person && p instanceof Class &&
- n instanceof Ninja && n instanceof Person && n instanceof Class
来源: http://www.qdfuns.com/article/27225/4eacb6954396be5d94d2848dd979f518.html