backbone的extend(0.9.2)
0.9.2版 原创,转载请标明 3Q....
1 var AppView = Backbone.View.extend({ 2 3 4 5 }) 6 7 console.log(AppView)
AppView是 Backbone.View 的一个视图模型子类,即AppView是父类返回的一个新的构造函数
源代码如下:
var extend = function(protoProps, staticProps) { var parent = this; var child; if (protoProps && protoProps.hasOwnProperty('constructor')) { child = protoProps.constructor; } else { child = function(){ parent.apply(this, arguments); }; } _.extend(child, parent); ctor.prototype = parent.prototype; child.prototype = new ctor(); if (protoProps) _.extend(child.prototype, protoProps); if (staticProps) _.extend(child, staticProps); child.prototype.constructor = child; child.__super__ = parent.prototype; return child; }; Model.extend = Collection.extend = Router.extend = View.extend = extend;
以上代码其实就是JS的原型继承,无非就是把 静态方法 与 原型方法克隆到 一个新的对象上
具体:
extend 函数中定义了3个参数
this 代表父类 parent
protoProps 实例属性
staticProps 静态属性
就上面例子而言就是 parent就是Backbone.Model , protoProps 是传进去的{}对象,staticProps 还木定义
1 /** 2 * 辅助工具 3 * **/ 4 5 //共享空构造函数来帮助创建原型链。代理模式 6 var ctor = function () { 7 }; 8 9 // Helper function to correctly set up the prototype chain, for subclasses. 10 // Similar to `goog.inherits`, but uses a hash of prototype properties and 11 // class properties to be extended. 12 //parent, protoProps, staticProps 13 //父类,实例属性,静态属性 14 var inherits = function (parent, protoProps, staticProps) { 15 //构造的实例对象 16 var child; 17 18 //判断protoProps是否一个原型对象(prototype),如果是则将child赋值为原型对象所属的构造函数 19 if (protoProps && protoProps.hasOwnProperty('constructor')) { 20 child = protoProps.constructor; 21 } else { 22 //当子类没有提供特定的constructor的时候,应该调用父类的。 23 /** 24 * 否则将新建一个构造函数赋值给child 25 * child = function () {}其实是要在new的时候才会 26 * 调用的,所以我们先假设我们设置的字段里面没有constructor, 27 * 所以当我们通过var temptA = new Tempt()的时候, 28 * 调用的是function () {Model.apply(temptA, arguments)}, 29 * **/ 30 child = function () { 31 //inherits函数返回的是一个构造函数,我们会用new child()来调用此构造函数 32 //(例如:AppView = Backbone.View.extend({});var appView=new AppView();), 33 // 所以此处的this指向我们new的实例(例如var appView=new AppView(),则this指向appView) 34 //new AppView进行的操作其实是Backbone.Model.apply(this,arguments) , 35 // 也就是说我们实例化appView的时候其实是调用Backbone.Model 36 37 //实例对象调用Backbone.Model 38 parent.apply(this, arguments); 39 }; 40 } 41 42 //复制静态属性parent -> child ,模型的属性复制给实例对象 43 _.extend(child, parent); 44 45 /**代理继承 46 * proxy来实现继承,这样就避免了在classical继承中出现的parent的constructor被使用两次带来 47 * 的效率问题和在原型链中再次继承this的属性 48 * function obj (o){ 49 * var f = {} 50 * f.prototype = o 51 * return new f(); 52 * } 53 */ 54 //ctor是一个内容为空的构造函数,此处将其原型对象设置为Backbone.View.prototype 55 ctor.prototype = parent.prototype; 56 //将child的原型对象设置为一个ctor的实例,child.prototype.contructor指向ctor 57 child.prototype = new ctor(); 58 59 /** 60 * 给新的类指定实例属性和静态属性的功能 61 * **/ 62 //将Backbone.View.extend的第二个参数(一般是一个对象)的的所有属性复制到child.prototype 63 if (protoProps) _.extend(child.prototype, protoProps); 64 65 //将Backbone.View.extend的第三个参数(一般是一个对象)的的所有属性复制到child,也就是给child设置静态属性或方法 66 if (staticProps) _.extend(child, staticProps); 67 68 //执行完child.prototype=new ctor后,child.prototype.constructor已经不指向child,所以此处需要显示设置 69 child.prototype.constructor = child; 70 71 //EcmaScript中并没有定义__super__这个属性,此处应该是backbone记录child对应的super类 72 child.__super__ = parent.prototype; 73 74 return child; 75 76 /** 77 * new 自定义View等() 所属类--> child(用户创造的构造函数) 78 * 原型对象--> ctor的一个实例(我们自定义的一些函数和方法都设置到此实例上) 79 * 原型对象--> Backbon.View.prototype 80 * **/ 81 };