jQuery.extend()的实现方式
jQuery.extend()的实现方式
jQuery中的extend()
extend()函数是jQuery的基础函数之一,作用是扩展现有的对象。例如下面的代码:
<script type="text/javascript" src="jquery-1.5.2.js"></script><script>obj1 = { a : 'a', b : 'b' };obj2 = { x : { xxx : 'xxx', yyy : 'yyy' }, y : 'y' };$.extend(true, obj1, obj2);alert(obj1.x.xxx); // 得到"xxx"obj2.x.xxx = 'zzz';alert(obj2.x.xxx); // 得到"zzz"alert(obj1.x.xxx); // 得带"xxx"</script>$ = { extend : function(target, options) { for (name in options) { target[name] = options[name]; } return target; }};<script type="text/javascript" src="jquery-extend.js"></script><script>obj1 = { a : 'a', b : 'b' };obj2 = { x : { xxx : 'xxx', yyy : 'yyy' }, y : 'y' };$.extend(obj1, obj2);alert(obj1.x.xxx); // 得到"xxx"obj2.x.xxx = 'zzz';alert(obj2.x.xxx); // 得到"zzz"alert(obj1.x.xxx); // 得带"zzz"</script>$ = {extend : function(deep, target, options) {for (name in options) {copy = options[name];if (deep && copy instanceof Array) { target[name] = $.extend(deep, [], copy); } else if (deep && copy instanceof Object) { target[name] = $.extend(deep, {}, copy);} else {target[name] = options[name];}}return target;}};<script type="text/javascript" src="jquery-extend.js"></script><script>obj1 = { a : 'a', b : 'b' };obj2 = { x : { xxx : 'xxx', yyy : 'yyy' }, y : 'y' };$.extend(true, obj1, obj2);alert(obj1.x.xxx); // 得到"xxx"obj2.x.xxx = 'zzz';alert(obj2.x.xxx); // 得到"zzz"alert(obj1.x.xxx); // 得到"xxx"</script>$ = function() { var copyIsArray, toString = Object.prototype.toString, hasOwn = Object.prototype.hasOwnProperty; class2type = { '[object Boolean]' : 'boolean', '[object Number]' : 'number', '[object String]' : 'string', '[object Function]' : 'function', '[object Array]' : 'array', '[object Date]' : 'date', '[object RegExp]' : 'regExp', '[object Object]' : 'object' }, type = function(obj) { return obj == null ? String(obj) : class2type[toString.call(obj)] || "object"; }, isWindow = function(obj) { return obj && typeof obj === "object" && "setInterval" in obj; }, isArray = Array.isArray || function(obj) { return type(obj) === "array"; }, isPlainObject = function(obj) { if (!obj || type(obj) !== "object" || obj.nodeType || isWindow(obj)) { return false; } if (obj.constructor && !hasOwn.call(obj, "constructor") && !hasOwn.call(obj.constructor.prototype, "isPrototypeOf")) { return false; } var key; for (key in obj) { } return key === undefined || hasOwn.call(obj, key); }, extend = function(deep, target, options) { for (name in options) { src = target[name]; copy = options[name]; if (target === copy) { continue; } if (deep && copy && (isPlainObject(copy) || (copyIsArray = isArray(copy)))) { if (copyIsArray) { copyIsArray = false; clone = src && isArray(src) ? src : []; } else { clone = src && isPlainObject(src) ? src : {}; } target[name] = extend(deep, clone, copy); } else if (copy !== undefined) { target[name] = copy; } } return target; }; return { extend : extend };}();func = function(){...};$ = func(); 也就是立即执行函数,并将结果赋给$。这种写法可以利用function来管理作用域,避免局部变量或局部函数影响全局域。另外,我们只希望使用者调用$.extend(),而将内部实现的函数隐藏,因此最终返回的对象中只包含extend: return { extend : extend }; if (target === copy) { continue; } 这是为了避免无限循环,要复制的属性copy与target相同的话,也就是将“自己”复制为“自己的属性”,可能导致不可预料的循环。 type = function(obj) { return obj == null ? String(obj) : class2type[toString.call(obj)] || "object"; }, isArray = Array.isArray || function(obj) { return type(obj) === "array"; } 如果浏览器有内置的Array.isArray 实现,就使用浏览器自身的实现方式,否则将对象转为String,看是否为"[object Array]"。if (!obj || type(obj) !== "object" || obj.nodeType || isWindow(obj)) { return false;} 如果定义了obj.nodeType,表示这是一个DOM元素;这句代码表示以下四种情况不进行深复制: if (obj.constructor && !hasOwn.call(obj, "constructor") && !hasOwn.call(obj.constructor.prototype, "isPrototypeOf")) { return false; } 如果对象具有构造函数,但却不是自身的属性,说明这个构造函数是通过prototye继承来的,这种情况也不进行深复制。这一点可以结合下面的代码结合进行理解: var key; for (key in obj) { } return key === undefined || hasOwn.call(obj, key); 这几句代码是用于检查对象的属性是否都是自身的,因为遍历对象属性时,会先从自身的属性开始遍历,所以只需要检查最后的属性是否是自身的就可以了。<script type="text/javascript" src="jquery-1.5.2.js"></script><script>function O() {this.yyy = 'yyy';}function X() {this.xxx = 'xxx';}X.prototype = new O();x = new X();obj1 = { a : 'a', b : 'b' };obj2 = { x : x };$.extend(true, obj1, obj2);alert(obj1.x.yyy); // 得到"xxx"obj2.x.yyy = 'zzz';alert(obj1.x.yyy); // 得到"zzz"</script> 可以看到,这种情况是不进行深复制的。