jQuery.extend和jQuery.jquery fn.extend方法的区别

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
您的访问请求被拒绝 403 Forbidden - ITeye技术社区
您的访问请求被拒绝
亲爱的会员,您的IP地址所在网段被ITeye拒绝服务,这可能是以下两种情况导致:
一、您所在的网段内有网络爬虫大量抓取ITeye网页,为保证其他人流畅的访问ITeye,该网段被ITeye拒绝
二、您通过某个代理服务器访问ITeye网站,该代理服务器被网络爬虫利用,大量抓取ITeye网页
请您点击按钮解除封锁&$.extend()方法在JQuery中有两个用法,第一种是扩展方法,第二种是用jquery实现的继承方式
jQuery.extend
对jQuery对象的扩展,可以理解为静态方法,是全局的,不需要实例jQuery就可以使用。
JAVASCRIPT:
jQuery.extend({
&&& min: function(a, b) {& return a & b ? a : },
&&& max: function(a, b) { return a & b ? a : }
2& jQuery实现的继承方式
jQuery.extend([deep], target, object1, [objectN])
返回值:Object
把2个对象合并得到新的target,deep是可选的(递归合并)
合并 settings 和 options,修改并返回 settings。
jQuery 代码:
var settings = { validate: false, limit: 5, name: "foo" }; var options = { validate: true, name: "bar" }; jQuery.extend(settings, options);
settings == { validate: true, limit: 5, name: "bar" }
合并 defaults 和 options, 不修改 defaults。
jQuery 代码:
var empty = {}; var defaults = { validate: false, limit: 5, name: "foo" }; var options = { validate: true, name: "bar" }; var settings = jQuery.extend(empty, defaults, options);
settings == { validate: true, limit: 5, name: "bar" }
empty == { validate: true, limit: 5, name: "bar" }
jQuery.fn.extend
对jQuery元素的扩展,只能用在jQuery元素上,可以理解为普通方法。定义插件时需要返回this,以支持jQuery的链式操作。
JAVASCRIPT:
&&&&jQuery.fn.extend({
&&&&&&red: function() {
&&&&&&&&return $(this).css('color', '#ff0000');
&&&&$('#test').red();
阅读(...) 评论()jQuery中extend()和fn.extend()方法详解
投稿:hebedich
字体:[ ] 类型:转载 时间:
jQuery自定义了jQuery.extend()和jQuery.fn.extend()方法.其中jQuery.extend()方法能够创建全局函数或者选择器,而jQuery.fn.extend()方法能够创建jQuery对象方法.
这两个方法用的是相同的代码,一个用于给jQuery对象或者普通对象合并属性和方法一个是针对jQuery对象的实例,对于基本用法举几个例子:
html代码如下:
&!doctype html&
&&&&& &title&&/title&
&&&&&&& &script src='jquery-1.7.1.js'&&/script&
&& &/head&
&&& &img src=''/&
&& &/body&
下面写js里面的用法:
合并两个普通对象
&&&&& //给两个普通对象合并属性
&&&&& var obj1={name:'Tom',age:22};
&&&&& var obj2={name:'Jack',height:180};
&&&&& console.log($.extend(obj1,obj2));& //Object {name: "Jack", age: 22, height: 180}
给jQuery对象添加属性或者方法
$.extend({hehe:function(){alert('hehe');}});
&$.hehe();& //alert('hehe')
这个用法很重要,是jQuery内部添加实例属性和方法以及原型属性和方法的实现方法也是编写jQuery插件的方法,下面是jQuery1.7.1中使用extend方法扩展自己的方法和属性
jQuery.extend({
&&& noConflict: function( deep ) {
&&&&&&& if ( window.$ === jQuery ) {
&&&&&&&&&&& window.$ = _$;
&&&&&&& if ( deep && window.jQuery === jQuery ) {
&&&&&&&&&&& window.jQuery = _jQ
&&&&&&& return jQ
&&& // Is the DOM ready to be used&#63; Set to true once it occurs.
&&& isReady: false,
&&& // A counter to track how many items to wait for before
&&& // the ready event fires. See #6781
&&& readyWait: 1,
在这个例子中只传入了一个对象参数,那么默认就把this当做待合并修改的对象
给jQuery对象实例添加属性或者方法
&//针对jQuery实例扩展合并
&&&&& console.log($('img').extend({'title':'img'}));//[img, img#img.img, prevObject: jQuery.fn.jQuery.init[1], context: document, selector: "img", title: "img", constructor: function…]
只合并不修改待合并对象
&&&&& var obj1={name:'Tom',age:22};
&&&&& var obj2={name:'Jack',height:180};
&&&&& console.log($.extend(obj1,obj2));&& //Object {name: "Jack", age: 22, height: 180}
&&&&& console.log(obj1);&&&&&&&&&&&&&&&&& //Object {name: "Jack", age: 22, height: 180}
默认情况下,待合并对象跟返回结果一样是被修改了的,如果仅仅想得到一个合并后的对象又不想破坏任何一个原来的对象可以使用此方法
& var obj1={name:'Tom',age:22};
& var obj2={name:'Jack',height:180};
& var empty={};
& console.log($.extend(empty,obj1,obj2));&& //Object {name: "Jack", age: 22, height: 180}
& console.log(obj1);&&&&&&&&&&&&&&&&& //Object {name: "Tom", age: 22}
使用则递归合并或者叫深度拷贝
&var obj1={name:'Tom',love:{drink:'milk',eat:'bread'}};
&var obj2={name:'Jack',love:{drink:'water',sport:'football'}};
&console.log(($.extend(false,obj1,obj2)).love);&& //Object {drink: "water", sport: "football"}
&console.log(($.extend(true,obj1,obj2)).love);&&& //Object {drink: "water", eat: "bread", sport: "football"}
详细的使用方法可以看参考手册
下面来分析下1.7.1源码中是怎么实现的:
jQuery.extend = jQuery.fn.extend = function() {
&&& var options, name, src, copy, copyIsArray, clone,
&&&&&&& target = arguments[0] || {},
&&&&&&& i = 1,
&&&&&&& length = arguments.length,
&&&&&&& deep =
&&&&&& ...
&首先是定义了一组变量,因为参数个数不确定所以就直接调用arguments对象访问传递的参数
& 变量 options:指向某个源对象。
&#137; &#137; 变量 name:表示某个源对象的某个属性名。
&#137; &#137; 变量 src:表示目标对象的某个属性的原始值。
&#137; &#137; 变量 copy:表示某个源对象的某个属性的值。
&#137; &#137; 变量 copyIsArray:指示变量 copy 是否是数组。
&#137; &#137; 变量 clone:表示深度复制时原始值的修正值。
&#137; &#137; 变量 target:指向目标对象。
&#137; &#137; 变量 i:表示源对象的起始下标。
&#137; &#137; 变量 length:表示参数的个数,用于修正变量 target。
&#137; &#137; 变量 deep:指示是否执行深度复制,默认为 false。
为了更好地了解代码实现这里以上面举的一个例子作为演示观察源代码执行情况
&&&&& var obj1={name:'Tom',love:{drink:'milk',eat:'bread'}};
&&&&& var obj2={name:'Jack',love:{drink:'water',sport:'football'}};
&&&&& $.extend(true,obj1,obj2)
// Handle a deep copy situation
&&& if ( typeof target === "boolean" ) {
&&&&&&& deep =
&&&&&&& target = arguments[1] || {};
&&&&&&& // skip the boolean and the target
&&&&&&& i = 2;
判断是不是深度复制,如果第一个参数是布尔值那么就把第一个参数的值给deep,然后把第二个参数作为目标对象,如果第二个参数不存在就赋值为一个空对象,把源对象的下标改为2,在这个例子里面& 是走这里的因为第一个参数是ture然后把deep变成了true ,target被修正成了第二个参数也即是obj1,源对象的起始下标为2就是从第三个开始作为源对象也就是本例中的obj2
// 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 ( length === i ) {
&&&&&&& target =
&&&&&&& --i;
如果length属性等于i的值那就表示没有目标对象存在,正常情况下length应该是大于i的值的 ,那么这个时候就把this作为目标对象把i值减一实现length值大于i值(比i大1)
这个就是jQuery给自己扩展属性的方法的实现原理,只要不传入目标对象就可以啦
两种可能的情况:$.extend(obj)&&& 或者& $.extend(false/true,obj);
&&& for ( ; i & i++ ) {
&&&&&&& // Only deal with non-null/undefined values
&&&&&&& if ( (options = arguments[ i ]) != null ) {
&&&&&&&&&&& // Extend the base object
&&&&&&&&&&& for ( name in options ) {
&&&&&&&&&&&&&&& src = target[ name ];
&&&&&&&&&&&&&&& copy = options[ name ];
&&&&&&&&&&&&&&& // Prevent never-ending loop
&&&&&&&&&&&&&&& if ( target === copy ) {
&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&& }
&&&&&&&&&&&&&&& // Recurse if we're merging plain objects or arrays
&&&&&&&&&&&&&&& if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) {
&&&&&&&&&&&&&&&&&&& if ( copyIsArray ) {
&&&&&&&&&&&&&&&&&&&&&&& copyIsArray =
&&&&&&&&&&&&&&&&&&&&&&& clone = src && jQuery.isArray(src) &#63; src : [];
&&&&&&&&&&&&&&&&&&& } else {
&&&&&&&&&&&&&&&&&&&&&&& clone = src && jQuery.isPlainObject(src) &#63; 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 ] =
&&&&&&&&&&&&&&& }
&&&&&&&&&&& }
这个部分就是此方法的核心了,从arguements对象的第i个下标值开始循环操作首先过滤掉源对象是null或者是undefined的情况可以看到其实
源对象不一定真的就是对像,也可以是其他类型的值比如字符串比如这样写:
console.log($.extend({'name':'tom'},'aa'));&& //Object {0: "a", 1: "a", name: "tom"}
是不是感觉很奇怪啊?究竟是怎么实现的呢?下面接着看
过滤完之后开始进行for循环 src保存的是目标对象的某个键的值,copy属性保存的源对象的某个键的值,这两个键都是一样的
// Prevent never-ending loop
&&&&&&&&&&&&&&& if ( target === copy ) {
&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&& }
如果源对象的某个属性值就是目标对象可能会造成死循环导致程序崩溃所以这里做了一个限制让其跳过此次循环例如:
var o = {};
$.extend( true, o, { n2: o } );
// 抛出异常:
// Uncaught RangeError: Maximum call stack size exceeded
但是这样做也会冤枉一些正常的情况比如:
&var obj1={a:'a'}
&var obj2={a:obj1};
&console.log($.extend(obj1,obj2)); //Object {a: "a"}
这种情况也是满足源对象值等于目标对象的但是结果发现obj1的a的属性值并没有被修改,就是因为执行了continue,下面把源码的这段话注释掉在执行
Object {a: Object}
这个时候就是正常被修改了个人感觉这个地方需要改进;
接着就是一个if判断就是区分是不是进行深度复制的先不看深度复制的先看一般的
target[ name ] =
很简单就是只要copy有值就直接复制给目标对象,目标对象有的就修改没有就增加,这样就实现了合并啦。
for循环之后在把新的目标对象返回,所以目标对象最后是被修改的,而且结果和返回的结果是一样的。
// Return the modified object
下面再来说说深度复制了怎么去处理
首先保证deep是true,copy有值并且是对象或者数组(如果不是对象和数组深度复制也就无从谈起)然后再分数组和对象来处理,先来看数组的情况:
if ( copyIsArray ) {
&&&&&&&& copyIsArray =
&&&&&&&& clone = src && jQuery.isArray(src) &#63; src : [];
&&&&&&& clone = src && jQuery.isPlainObject(src) &#63; src : {};
如果是数组copyIsArray的值为真然后走里面的 把值改成false ,针对当前循环的源对象属性,目标对象可能有也可能没有,有的话判断一下是不是数组是的话就是原来的数组不变不是的话就让它变成一个数组,因为既然源对象的当前属性是数组最后目标元素也必须是数组。不是数组就是对象把目标对象当前属性改成对象。
&&& // Never move original objects, clone them
&&&& target[ name ] = jQuery.extend( deep, clone, copy );
然后把源对象的当前属性值(是数组或对象)和已经被改造过的目标对象的当前属性进行递归合并最后返回的新的数组或者对象赋值给目标对象,最终实现了深度复制。
但是这里面还有一个比较奇怪的现象,比如这样操作:
&&&&& console.log($.extend({a:1},'aa')); //Object {0: "a", 1: "a", a: 1}
原来源对象不一定真的是对象e而且居然可以把字符串拆开跟目标对象合并,原来for...in循环是操作字符串的
&&&&& var str='aa';
&&&&& for(var name in str){&
&&&&&&&& console.log(name);
&&&&&&&& console.log(str[name])
这样也是可以的,会把字符串拆开按数字下标读取,但是在源码中
if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) )
是有数组和对象限制的,那么深度复制的时候是不是就没有效果了呢?
经过我测试深度复制也是可以的,因为在源码里面copy的值竟然变成了匿名函数函数
&alert(jQuery.isPlainObject(copy)); //true
至于为什么是函数笔者还没搞清楚留待以后解决吧!
您可能感兴趣的文章:
大家感兴趣的内容
12345678910
最近更新的内容
常用在线小工具其他回答(4)
从你的代码来看,你并没有定义test1()这个实例方法,调用当然是无效的。
$("#test").test 算是一个表达式,控制台显示出它的值。因为是个普通函数,显示的就是它的函数代码了。
test() 的话,会执行这个函数,然后控制台显示返回值,你没写 return,所以就是 undefined 了
推荐一本书你去看一下,就了然啦!如何编写锋利的jquery,我就是看这个现在才略知一二,楼上答案的你可以参考。
园豆:3048
?????????text1()哪里定义了啊
&&&您需要以后才能回答,未注册用户请先。

我要回帖

更多关于 .fn.extend 参数 的文章

 

随机推荐