javascript框架设计-种子模块一

种子模块

种子模块是框架设计中的核心部分,也是框架最先执行的一部分,所以要极具扩展性、稳定性及常用性。常见框架的种子模块至少具有类型拓展、数组化、类型判定、简单事件的绑定与卸载、无冲突处理、模块加载及domReady功能。

1、无冲突处理

参考jQuery源码,原理:利用临时变量将同命名变量或不同版本同框架(如jQuery版本很多)保存下来,然后使用函数处理控制权。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
//jQuery noConflict源码
var _$ = window.$, _jQuery = window.jQuery;
$.extend({
noConflict: function(deep) {
if (window.$ == jQuery) {
window.$ = _$;
}
if (deep && window.$ == jQuery) {
window.jQuery = _jQuery;
}
}
});

具体详情分析,请参看上篇jqeury中的noConflict机制;

2、类型拓展

类型拓展是一个框架必须具有的功能,也就是我们需要在我们的命名空间上拓展功能,这也就是为什么jQuery会有这么多的插件,因为jQuery的$.extend 或 $.fn.extend函数。

一个最简单的extend的实现

1
2
3
4
5
6
var extend = function(target, source) {
for (var key in source) {
target[key] = source[key];
}
return target;
};

接下来我们分析下jQuery中的extend的实现:我这里使用最新的3.0,应该无差异

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
jQuery.extend = jQuery.fn.extend = function() {
var options, name, src, copy, copyIsArray, clone,
target = arguments[ 0 ] || {}, //默认复制到的目标为第一个参数
i = 1, //从第二个参数开始后面的算source
length = arguments.length,
deep = false; //是否深复制
// Handle a deep copy situation
if ( typeof target === "boolean" ) { //如果第一个参数为boolean,处理深复制
deep = target;
// Skip the boolean and the target //此时从第三个参数算source
target = arguments[ i ] || {};
i++;
}
// Handle case when target is a string or something (possible in deep copy)
if ( typeof target !== "object" && !jQuery.isFunction( target ) ) { //处理如果target不是对象
target = {};
}
// Extend jQuery itself if only one argument is passed
if ( i === length ) { //如果只有个一个参数,则拓展自身,jQuery插件的写法
target = this;
i--;
}
for ( ; i < length; i++ ) {
// Only deal with non-null/undefined values
if ( ( options = arguments[ i ] ) != null ) { //null不处理
// Extend the base object
for ( name in options ) { //遍历对象
src = target[ name ]; //用src,copy处理,对target,resource对象不改变
copy = options[ name ];
// Prevent never-ending loop
if ( target === copy ) { //如果两个字段相等,跳过
continue;
}
// Recurse if we're merging plain objects or arrays
if ( deep && copy && ( jQuery.isPlainObject( copy ) ||
( copyIsArray = jQuery.isArray( copy ) ) ) ) {
if ( copyIsArray ) { //数组
copyIsArray = false;
clone = src && jQuery.isArray( src ) ? src : [];
} else { //对象
clone = src && jQuery.isPlainObject( src ) ? src : {};
}
// Never move original objects, clone them
target[ name ] = jQuery.extend( deep, clone, copy );
// Don't bring in undefined values
} else if ( copy !== undefined ) {
target[ name ] = copy;
}
}
}
}
// Return the modified object
return target;
};

自己写的一个,造造轮子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
var extend = function(target, source) {
var args = [].slice.call(arguments), i = 1, key,
ride = typeof args[args.length - 1] == 'boolean' ? args.pop() : true;
if (args.length == 1) {
target = this.window ? {} : this;
i = 0;
}
while ((source = args[i++])) {
for (key in source) {
//ride 为false,则不覆盖target同名字段
if (Object.hasOwnProperty.call(source, key) && (ride || !(key in target))) {
target[key] = source[key];
}
}
}
return target;
};