知识大全 jQuery.extend()的实现方式详解及实例
Posted 属性
篇首语:智慧并不产生于学历,而是来自对于知识的终生不懈的追求。本文由小常识网(cha138.com)小编为大家整理,主要介绍了知识大全 jQuery.extend()的实现方式详解及实例相关的知识,希望对你有一定的参考价值。
jQuery.extend()的实现方式详解及实例 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!
extend()函数是jQuery的基础函数之一 作用是扩展现有的对象 复制代码 代码如下: <script type=text/javascript src=jquery js></script> <script> obj = a : a b : b ; obj = x : xxx : xxx yyy : yyy y : y ;$ extend(true obj obj );
alert(obj x xxx); // 得到"xxx"
obj x xxx = zzz ; alert(obj x xxx); // 得到"zzz" alert(obj x xxx); // 得带"xxx" </script>
$ extend(true obj obj )表示以obj 中的属性扩展对象obj 第一个参数设为true表示深复制 虽然obj 中原来没有"x"属性 但经过扩展后 obj 不但具有了"x"属性 而且对obj 中的"x"属性的修改也不会影响到obj 中"x"属性的值 这就是所谓的“深复制”了
浅复制的实现
如果仅仅需要实现浅复制 可以采用类似下面的写法
复制代码 代码如下: $ = extend : function(target options) for (name in options) target[name] = options[name]; return target; ;也就是简单地将options中的属性复制到target中 我们仍然可以用类似的代码进行测试 但得到的结果有所不同(假设我们的js命名为“jquery extend js”)
复制代码 代码如下: <script type=text/javascript src=jquery extend js></script> <script> obj = a : a b : b ; obj = x : xxx : xxx yyy : yyy y : y ; $ extend(obj obj ); alert(obj x xxx); // 得到"xxx" obj x xxx = zzz ; alert(obj x xxx); // 得到"zzz" alert(obj x xxx); // 得带"zzz" </script>obj 中具有了"x"属性 但这个属性是一个对象 对obj 中的"x"的修改也会影响到obj 这可能会带来难以发现的错误
深复制的实现
如果我们希望实现“深复制” 当所复制的对象是数组或者对象时 就应该递归调用extend 如下代码是“深复制”的简单实现
复制代码 代码如下: $ = 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; ;具体分为三种情况 属性是数组时 则将target[name]初始化为空数组 然后递归调用extend 属性是对象时 则将target[name]初始化为空对象 然后递归调用extend 否则 直接复制属性
测试代码如下
复制代码 代码如下: <script type=text/javascript src=jquery extend js></script> <script> obj = a : a b : b ; obj = x : xxx : xxx yyy : yyy y : y ; $ extend(true obj obj ); alert(obj x xxx); // 得到"xxx" obj x xxx = zzz ; alert(obj x xxx); // 得到"zzz" alert(obj x xxx); // 得到"xxx" </script>现在如果指定为深复制的话 对obj 的修改将不会对obj 产生影响了 不过这个代码还存在一些问题 比如“instanceof Array”在IE 中可能存在不兼容的情况 jQuery中的实现实际上会更复杂一些
更完整的实现
下面的实现与jQuery中的extend()会更接近一些
复制代码 代码如下: $ = function() var copyIsArray toString = Object prototype toString hasOwn = Object prototype hasOwnProperty;class type = [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) : class type[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 ; ();
首先是 $ = function() ();这种写法 可以理解为与下面的写法类似
复制代码 代码如下: func = function() ; $ = func();也就是立即执行函数 并将结果赋给$ 这种写法可以利用function来管理作用域 避免局部变量或局部函数影响全局域 另外 我们只希望使用者调用$ extend() 而将内部实现的函数隐藏 因此最终返回的对象中只包含extend:
复制代码 代码如下: return extend : extend ;接下来 我们看看extend函数与之前的区别 首先是多了这句话
复制代码 代码如下: if (target === copy) continue;这是为了避免无限循环 要复制的属性copy与target相同的话 也就是将“自己”复制为“自己的属性” 可能导致不可预料的循环
然后是判断对象是否为数组的方式
复制代码 代码如下: type = function(obj) return obj == null ? String(obj) : class type[toString call(obj)] || "object"; isArray = Array isArray || function(obj) return type(obj) === "array";如果浏览器有内置的Array isArray 实现 就使用浏览器自身的实现方式 否则将对象转为String 看是否为"[object Array]"
最后逐句地看看isPlainObject的实现
复制代码 代码如下: if (!obj || type(obj) !== "object" || obj nodeType || isWindow(obj)) return false;如果定义了obj nodeType 表示这是一个DOM元素 这句代码表示以下四种情况不进行深复制 对象为undefined 转为String时不是"[object Object]" obj是一个DOM元素 obj是window 之所以不对DOM元素和window进行深复制 可能是因为它们包含的属性太多了 尤其是window对象 所有在全局域声明的变量都会是其属性 更不用说内置的属性了
接下来是与构造函数相关的测试
复制代码 代码如下: 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);这几句代码是用于检查对象的属性是否都是自身的 因为遍历对象属性时 会先从自身的属性开始遍历 所以只需要检查最后的属性是否是自身的就可以了 这 说明如果对象是通过prototype方式继承了构造函数或者属性 则不对该对象进行深复制 这可能也是考虑到这类对象可能比较复杂 为了避免引入不确定 的因素或者为复制大量属性而花费大量时间而进行的处理 从函数名也可以看出来 进行深复制的只有"PlainObject" 如果我们用如下代码进行测试
复制代码 代码如下: <script type=text/javascript src=jquery js></script> <script> function O() this yyy = yyy ;function X() this xxx = xxx ;
X prototype = new O();
x = new X();
obj = a : a b : b ; obj = x : x ; $ extend(true obj obj );
alert(obj x yyy); // 得到"xxx" obj x yyy = zzz ; alert(obj x yyy); // 得到"zzz" </script>
cha138/Article/program/Java/JSP/201311/19999相关参考
Jar文件包间接及Jar命令开发实例详解 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧! 常常看到
Nginx负载均衡配置实例详解 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!负载均衡是我们大流量网
C#TextBox事件实现实例详解 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧! C#TextB
知识大全 js replace 与replaceall实例用法详解
这篇文章介绍了jsreplace与replaceall实例用法详解有需要的朋友可以参考一下 stringObjreplace(rgExpreplaceText)参数stringObj必选
Spring中IoC的入门实例详解 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧! Spring的
.NET中自定义配置节点实例详解 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧! 一目的 一般应
Oracle实例和Oracle数据库详解 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧! 一ORA
ASP.NET挪用淘宝API实例详解 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧! &n
大家都知道吧在struts中提供了一些常用的******其中就包括对异常处理的******我们直接声明使用即可很方便的哟!下面来举个例子说明一下 &nbs
实例结构 oracle实例=内存结构+进程结构 oracle实例启动的过程其实就是oracle内存参数设置的值加载到内存中并启动相应的后台进程进行相关的服务过程 进程结构 oracle进程