backbond中的M,指的是模型,即存放数据以及数据相关逻辑的单位。在分析其结构之前,先看一下其调用过程。

<script>

    (function ($) {
World = Backbone.Model.extend({
initialize: function(){
alert('Hey, you create me!');
},
defaults: {
name:'张三',
age: '38'
}
}); var wodld = new World({x:1});
var x = new World({y:2}); })(jQuery);

backbond 通过Backbone.Model.extend方法得到一个World类(为了不让World和其实例化结果混淆,这里把World称为类,实例化结果称为对象),再通过实例化World来获得实例对象,并调用类中的initialize方法。这看起来和java很相似,也就是一种面向对象的编程方法。

在前面的backbond架构分析中,我们知道Backbone.Model.extend就是extend函数,从extend入手分析,先看一下extend在内部的实现。

var extend = function(protoProps, staticProps) {
var parent = this;
var child; // 如果传入的对象中存在属性为construtor,那么将其构造函数作为child
// 否则,child作为一个调用父类的方法
if (protoProps && _.has(protoProps, 'constructor')) {
child = protoProps.constructor;
} else {
child = function(){ return parent.apply(this, arguments); };
}
// 调用underscore的extend方法 将传入的第二个参数添加进child
_.extend(child, parent, staticProps); // 对原型链进行设置 通过创建一个surrogate来使得child的原型链获得parent原型链
// 如果直接赋值 即child.prototype = parent.prototype,那么对child.prototype的改造也会影响到parent.prototype
var Surrogate = function(){ this.constructor = child; };
Surrogate.prototype = parent.prototype;
child.prototype = new Surrogate; // Add prototype properties (instance properties) to the subclass,
// if supplied.
if (protoProps) _.extend(child.prototype, protoProps); // 最后,由于上面的改造原型链,需要将child的上一层原型改为parent
child.__super__ = parent.prototype;
return child;
};

在extend中,最后返回的是一个函数,也就是上面例子中的World类,extend中的parent也就是Backbone.Model,即使得返回的函数的原型上具有Model和我们传入的属性。

接下来就是Model函数了,

var Model = Backbone.Model = function(attributes, options) {
//设置属性
var attrs = attributes || {};
options || (options = {});
this.cid = _.uniqueId('c');
this.attributes = {};
if (options.collection) this.collection = options.collection;
if (options.parse) attrs = this.parse(attrs, options) || {};
attrs = _.defaults({}, attrs, _.result(this, 'defaults'));
this.set(attrs, options);
this.changed = {};
//调用initialize函数
this.initialize.apply(this, arguments);
};

我们知道,在js中使用new字符调用一个函数时,也就是创建了一个对象,this指向了这个对象并使该对象继承了构造函数的原型链,最后如果返回结果不是一个对象的话就返回这个对象。

那么在上面的例子中,最后通过了var world = new World({x:1});调用了World类,

而一开始我们在构造World类时并没有传入具有属性为constructor的对象,也就是说 World = function(){ return BackBond.Model.apply(this, arguments); };

其中的this就是新创建的对象,那么就在新创建的对象下调用了Backbond.Model,最后返回了这个对象,也就是我们上面的world对象。

最后我们在调试器打印出world对象。

最后,总结一下backbond具体的设计思路:

   1: 定义Model函数,并在其原型上设置一系列方法。

2.1: 通过extend函数,获得一个函数(也就是我们创建的类),其原型继承了Model函数原型

2.2: 并根据我们传入的参数设置类为一个构造函数或者通过apply将上下文设置为我们的实例化对象来调用Model函数的函数(即初始化,并调用initlize函数,相当于java的构造函数)。

2.3: 最后返回类。

   3: 实例化父类,获得对象。

这样的设计最终会使得我们像使用面向对象语言一样来使用Js。(类,构造函数,对象,继承...)。

最新文章

  1. Bootstrap人民币玩家攻略
  2. window.location 结构
  3. PLSQL_基础系列12_替换函数用法REPLACE / TRANSLATE / REGEXP_REPLACE
  4. React 初探
  5. 49.关于Quartus和ISE中ROM的初始化和仿真的一些小结
  6. 网站中的专题页或者tag聚合页的权重不错
  7. [html]html常用代码
  8. Linux shell 的 test 命令用法详解
  9. HtmlAgilityPack + Fizzler
  10. 关于position:fixed;的居中问题
  11. Linux(二)CentOS的安装
  12. HNOI2019做题笔记
  13. 查看局域网内所有IP的方法
  14. zookeeper 四字命令的使用
  15. JavaSE 可变参数的方法重载
  16. angularjs的ng-change事件演示
  17. 远程服务器返回了意外相应:(413) Request Entity Too Large。
  18. webbrowser 响应关闭事件
  19. MyCAT入门实践
  20. 洛谷 P1865 A % B Problem

热门文章

  1. 20145232韩文浩《网络对抗》逆向及BOF基础实践
  2. STM32的SWD调试进不了main函数
  3. Android逆向之smali学习
  4. 基于react可无限向内部添加节点的tree
  5. Settings 参数记录
  6. 判断exe执行结束,事件监听
  7. 【腾讯Bugly干货分享】WebSocket 浅析
  8. CLion之C++框架篇-优化框架,引入boost(三)
  9. 你可以这么理解五种I/O模型
  10. Eclipse 中构建 Maven 项目的完整过程 - SpringBoot 项目