码迷,mamicode.com
首页 > 其他好文 > 详细

leaflet开源地图库源码研读(四)——OOP的基础构建(by vczero)

时间:2014-10-09 19:34:27      阅读:346      评论:0      收藏:0      [点我收藏+]

标签:des   style   blog   http   color   io   os   使用   ar   

一、贴源码

源码存放的目录是src->core->Class.js

bubuko.com,布布扣

bubuko.com,布布扣
 1 L.Class = function () {};
 2 
 3 L.Class.extend = function (props) {
 4 
 5     // extended class with the new prototype
 6     var NewClass = function () {
 7 
 8         // call the constructor
 9         if (this.initialize) {
10             this.initialize.apply(this, arguments);
11         }
12 
13         // call all constructor hooks
14         if (this._initHooks.length) {
15             this.callInitHooks();
16         }
17     };
18 
19     // jshint camelcase: false
20     var parentProto = NewClass.__super__ = this.prototype;
21 
22     var proto = L.Util.create(parentProto);
23     proto.constructor = NewClass;
24 
25     NewClass.prototype = proto;
26 
27     //inherit parent‘s statics
28     for (var i in this) {
29         if (this.hasOwnProperty(i) && i !== ‘prototype‘) {
30             NewClass[i] = this[i];
31         }
32     }
33 
34     // mix static properties into the class
35     if (props.statics) {
36         L.extend(NewClass, props.statics);
37         delete props.statics;
38     }
39 
40     // mix includes into the prototype
41     if (props.includes) {
42         L.Util.extend.apply(null, [proto].concat(props.includes));
43         delete props.includes;
44     }
45 
46     // merge options
47     if (proto.options) {
48         props.options = L.Util.extend(L.Util.create(proto.options), props.options);
49     }
50 
51     // mix given properties into the prototype
52     L.extend(proto, props);
53 
54     proto._initHooks = [];
55 
56     // add method for calling all hooks
57     proto.callInitHooks = function () {
58 
59         if (this._initHooksCalled) { return; }
60 
61         if (parentProto.callInitHooks) {
62             parentProto.callInitHooks.call(this);
63         }
64 
65         this._initHooksCalled = true;
66 
67         for (var i = 0, len = proto._initHooks.length; i < len; i++) {
68             proto._initHooks[i].call(this);
69         }
70     };
71 
72     return NewClass;
73 };
74 
75 
76 // method for adding properties to prototype
77 L.Class.include = function (props) {
78     L.extend(this.prototype, props);
79 };
80 
81 // merge new default options to the Class
82 L.Class.mergeOptions = function (options) {
83     L.extend(this.prototype.options, options);
84 };
85 
86 // add a constructor hook
87 L.Class.addInitHook = function (fn) { // (Function) || (String, args...)
88     var args = Array.prototype.slice.call(arguments, 1);
89 
90     var init = typeof fn === ‘function‘ ? fn : function () {
91         this[fn].apply(this, args);
92     };
93 
94     this.prototype._initHooks = this.prototype._initHooks || [];
95     this.prototype._initHooks.push(init);
96 };
View Code

二、代码分析

(1)在L的命名空间下,定义Class对象,以构造函数的形式给出。 

L.Class = function () {};

 (2)分别给Class对象添加静态方法extend 、include、mergeOptions、addInitHook。

 1 var L = {};
 2 L.Class = function(){};
 3 
 4 
 5 /*
 6 * 作用:扩展该类的prototype,继承父类的静态函数、静态属性等
 7 *
 8 * */
 9 L.Class.extend = function(props){};
10 /*
11  * 作用:添加属性到原型
12  * */
13 L.Class.include = function (props) {};
14 /*
15  * 作用:合并默认的options到Class
16  * */
17 L.Class.mergeOptions = function (options) {};
18 /*
19  * 作用:添加一个构造函数的钩子
20  * */
21 L.Class.addInitHook = function (fn){};

(3)分析L.Class.extend函数

贴上L.Class.extend函数的源码:

bubuko.com,布布扣
 1 L.Class.extend = function (props) {
 2 
 3     // extended class with the new prototype
 4     var NewClass = function () {
 5 
 6         // call the constructor
 7         if (this.initialize) {
 8             this.initialize.apply(this, arguments);
 9         }
10 
11         // call all constructor hooks
12         if (this._initHooks.length) {
13             this.callInitHooks();
14         }
15     };
16 
17     // jshint camelcase: false
18     var parentProto = NewClass.__super__ = this.prototype;
19 
20     var proto = L.Util.create(parentProto);
21     proto.constructor = NewClass;
22 
23     NewClass.prototype = proto;
24 
25     //inherit parent‘s statics
26     for (var i in this) {
27         if (this.hasOwnProperty(i) && i !== ‘prototype‘) {
28             NewClass[i] = this[i];
29         }
30     }
31 
32     // mix static properties into the class
33     if (props.statics) {
34         L.extend(NewClass, props.statics);
35         delete props.statics;
36     }
37 
38     // mix includes into the prototype
39     if (props.includes) {
40         L.Util.extend.apply(null, [proto].concat(props.includes));
41         delete props.includes;
42     }
43 
44     // merge options
45     if (proto.options) {
46         props.options = L.Util.extend(L.Util.create(proto.options), props.options);
47     }
48 
49     // mix given properties into the prototype
50     L.extend(proto, props);
51 
52     proto._initHooks = [];
53 
54     // add method for calling all hooks
55     proto.callInitHooks = function () {
56 
57         if (this._initHooksCalled) { return; }
58 
59         if (parentProto.callInitHooks) {
60             parentProto.callInitHooks.call(this);
61         }
62 
63         this._initHooksCalled = true;
64 
65         for (var i = 0, len = proto._initHooks.length; i < len; i++) {
66             proto._initHooks[i].call(this);
67         }
68     };
69 
70     return NewClass;
71 };
View Code

现在,来看NewClass对象,NewClass对象就是创建一个新的内部对象,所有父类的属性和方法都基于此方法。this.initialize就是构造函数。

 1 // extended class with the new prototype
 2 var NewClass = function () {
 3 
 4     // call the constructor
 5     if (this.initialize) {
 6         this.initialize.apply(this, arguments);
 7     }
 8 
 9     // call all constructor hooks
10     if (this._initHooks.length) {
11         this.callInitHooks();
12     }
13 };

 var parentProto = NewClass.__super__ = this.prototype; 将原型赋给NewClass的_super_属性,并赋值给parentProto。

var proto = L.Util.create(parentProto); //在LeafLet中有个Util.js,该工具类的方法的create方法的作用是:基于给定原型构建对象
proto.constructor = NewClass; //对象proto的构造函数指向NewClass

NewClass.prototype = proto; //NewClass的原型指向proto,这个大家可以看看原型链的继承方式

附:L.Util.create代码:

// create an object from a given prototype
    create: Object.create || (function () {
        function F() {}
        return function (proto) {
            F.prototype = proto;
            return new F();
        };
    })()

接着往下看:

//inherit parent‘s statics
    for (var i in this) {
        if (this.hasOwnProperty(i) && i !== ‘prototype‘) { //继承父类的静态属性和方法,hasOwnProperty只会遍历自定义属性和方法,不会遍历原型
            NewClass[i] = this[i];
        }
    }

再接着往下看:

// mix static properties into the class
    if (props.statics) {
        L.extend(NewClass, props.statics); //L.extend == L.Util.extend,在Util.js中便可找到,作用是扩展属性,这里是将props.statics的属性给了NewClass
        delete props.statics; //删除该属性
    }

    // mix includes into the prototype
    if (props.includes) {
        L.Util.extend.apply(null, [proto].concat(props.includes)); //apply这里巧妙的使用了null, 主要是为了使用extend的功能,将includes和proto的原型结合,连接成一个数组。
        delete props.includes; //删除该属性
    }

附:L.Util.extend源码

extend: function (dest) {
        var i, j, len, src;

        for (j = 1, len = arguments.length; j < len; j++) {
            src = arguments[j];
            for (i in src) {
                dest[i] = src[i];
            }
        }
        return dest;
    },

接着往下看:

// merge options
    if (proto.options) {
        props.options = L.Util.extend(L.Util.create(proto.options), props.options); //将options属性合并
    }

    // mix given properties into the prototype
    L.extend(proto, props); //将props的扩展属性,包括原型给proto

    proto._initHooks = [];  //初始化空的钩子数组

接着往下看:

// add method for calling all hooks
// 增加一个方法,调用所有的钩子
proto.callInitHooks = function () { if (this._initHooksCalled) { return; } //如果已经调用,直接return if (parentProto.callInitHooks) { //如果父类的原型中存在callInitHooks,则调用父类的callInitHooks parentProto.callInitHooks.call(this); } this._initHooksCalled = true; //设置调用后状态 for (var i = 0, len = proto._initHooks.length; i < len; i++) { proto._initHooks[i].call(this); //调用钩子的数组中的方法 } };

最后一步了,返回对象:

return NewClass;

(4)include:

// method for adding properties to prototype
L.Class.include = function (props) {
    L.extend(this.prototype, props);
};

(5)mergeOptions:

// merge new default options to the Class
L.Class.mergeOptions = function (options) {
    L.extend(this.prototype.options, options);
};

(6)addInitHook:

// add a constructor hook
L.Class.addInitHook = function (fn) { // (Function) || (String, args...)
    var args = Array.prototype.slice.call(arguments, 1);

    var init = typeof fn === ‘function‘ ? fn : function () {
        this[fn].apply(this, args);
    };

    this.prototype._initHooks = this.prototype._initHooks || [];
    this.prototype._initHooks.push(init);
};

三、用图来理理extend函数

bubuko.com,布布扣

 

上一篇:Leaflet开源地图库源码研读(三)——浏览器&移动设备判断(browser.js)(by vczero)

 

leaflet开源地图库源码研读(四)——OOP的基础构建(by vczero)

标签:des   style   blog   http   color   io   os   使用   ar   

原文地址:http://www.cnblogs.com/vczero/p/leaflet_4.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!