• backbond Model实现


    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。(类,构造函数,对象,继承...)。

  • 相关阅读:
    POJ1475 Pushing Boxes 华丽丽的双重BFS
    POJ3322 Bloxorz I 无脑广搜(我死了。。。)
    CH2401 送礼物 双向搜索
    POJ2248 Addition Chains 迭代加深
    POJ3074 Sudoku 剪枝深(神?)搜
    Luogu P1120 小木棍 [数据加强版] 来来来我们一起来剪枝,剪枝,剪枝、、、
    Luogu P4095 [HEOI2013]Eden 的新背包问题 思维/动规
    Luogu P5201 [USACO19JAN]Shortcut 最短路树???
    Luogu P5122 [USACO18DEC]Fine Dining 最短路
    Luogu P1608 路径统计 最短路计数
  • 原文地址:https://www.cnblogs.com/Darlietoothpaste/p/6623231.html
Copyright © 2020-2023  润新知