jQuery源码解读之extend()与工具方法、实例方法详解


Posted in jQuery onMarch 30, 2017

本文实例讲述了jQuery源码解读之extend()与工具方法、实例方法。分享给大家供大家参考,具体如下:

使用jQuery的时候会发现,jQuery中有的函数是这样使用的:

$.get();
$.post();
$.getJSON();

有些函数是这样使用的:

$('div').css();
$('ul').find('li');

有些函数是这样使用的:

$('li').each(callback);
$.each(lis,callback);

这里涉及到两个概念:工具方法与实例方法。通常我们说的工具方法是指无需实例化就可以调用的函数,如第一段代码;实例方法是必须实例化对象以后才可以调用的函数,如第二段代码。jQuery中很多方法既是实例方法也是工具方法,只是调用方式略有不同,如第三段代码。为了更清晰解释JavaScript中的工具方法与实例方法,进行如下测试。

function A(){
}
A.prototype.fun_p=function(){console.log("prototpye");};
A.fun_c=function(){console.log("constructor");};
var a=new A();
A.fun_p();//A.fun_p is not a function
A.fun_c();//constructor
a.fun_p();//prototpye
a.fun_c();//a.fun_c is not a function

通过以上测试可以得出结论,在原型中定义的是实例方法,在构造函数中直接添加的是工具方法;实例方法不能由构造函数调用,同理,工具方法也不能由实例调用。

当然实例方法不仅可以在原型中定义,有以下三种定义方法:

function A(){
    this.fun_f=function(){
        console.log("Iam in the constructor");
    };
}
A.prototype.fun_p=function(){
    console.log("Iam in the prototype");
};
var a=new A();
a.fun_f();//Iam in the constructor
a.fun_i=function(){
    console.log("Iam in the instance");
};
a.fun_i();//Iam in the instance
a.fun_p();//Iam in the prototype

这三种方式的优先级为:直接定义在实例上的变量的优先级要高于定义在“this”上的,而定义在“this”上的又高于 prototype定义的变量。即直接定义在实例上的变量会覆盖定义在“this”上和prototype定义的变量,定义在“this”上的会覆盖prototype定义的变量。

下面看jQuery中extend()方法源码:

jQuery.extend = jQuery.fn.extend = function() {
    var options,name, src, copy, copyIsArray, clone,
        target= arguments[0] || {},
        i =1,
        length= arguments.length,
        deep= false;
    // Handle adeep copy situation
    if ( typeoftarget === "boolean" ) {
        deep= target;
        //Skip the boolean and the target
        target= arguments[ i ] || {};
        i++;
    }
    // Handlecase when target is a string or something (possible in deep copy)
    if ( typeoftarget !== "object" && !jQuery.isFunction(target) ) {
        target= {};
    }
    // ExtendjQuery itself if only one argument is passed
    if ( i ===length ) {
        target= this;
        i--;
    }
    for ( ; i< length; 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 ) {
                   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;
                }
            }
        }
    }
    // Returnthe modified object
    return target;
};

(1)首先,jQuery和其原型中extend()方法的实现使用的同一个函数。

(2)当extend()中只有一个参数的时候,是为jQuery对象添加插件。在jQuery上扩展的叫做工具方法,在jQuery.fn(jQuery原型)中扩展的是实例方法,即使在jQuery和原型上扩展相同名字的函数也可以,使用jQuery对象会调用工具方法,使用jQuery()会调用实例方法。

(3)当extend()中有多个参数时,后面的参数都扩展到第一个参数上。

var a={};
$.extend(a,{name:"hello"},{age:10});
console.log(a);//Object{name: "hello", age: 10}

(4)浅拷贝(默认):

var a={};
varb={name:"hello"};
$.extend(a,b);
console.log(a);//Object{name: "hello"}
a.name="hi";
console.log(b);//Object{name: "hello"}

b不受a影响,但是如果b中一个属性为对象:

var a={};
varb={name:{age:10}};
$.extend(a,b);
console.log(a.name);//Object{age: 10}
a.name.age=20;
console.log(b.name);//Object{age: 20}

由于浅拷贝无法完成,则b.name会受到a的影响,这时我们往往希望深拷贝。

深拷贝:

var a={};
varb={name:{age:10}};
$.extend(true,a,b);
console.log(a.name);//Object{age: 10}
a.name.age=20;
console.log(b.name);//Object{age: 10}

b.name不受a的影响。

var a={name:{job:"Web Develop"}};
var b={name:{age:10}};
$.extend(true,a,b);
console.log(a.name);//age: 10 job: "Web Develop"
//b.name没有覆盖a.name.job。

希望本文所述对大家jQuery程序设计有所帮助。

jQuery 相关文章推荐
jquery实现图片放大点击切换
Jun 06 jQuery
jQuery复合事件用法示例
Jun 10 jQuery
jquery 一键复制到剪切板的实例
Sep 20 jQuery
jQuery Datatables表头不对齐的解决办法
Nov 27 jQuery
深入浅析angular和vue还有jquery的区别
Aug 13 jQuery
jQuery选择器之层次选择器用法实例分析
Feb 19 jQuery
jquery简单实现纵向的无缝滚动代码实例
Apr 01 jQuery
jquery分页优化操作实例分析
Aug 23 jQuery
jQuery单页面文字搜索插件jquery.fullsearch.js的使用方法
Feb 04 jQuery
jQuery+css实现的点击图片放大缩小预览功能示例【图片预览 查看大图】
May 29 jQuery
jquery简易手风琴插件的封装
Oct 13 jQuery
jQuery实现鼠标拖动图片功能
Mar 04 jQuery
jQuery实现Select下拉列表进行状态选择功能
Mar 30 #jQuery
基于jquery实现二级联动效果
Mar 30 #jQuery
jquery中关于bind()方法的使用技巧分享
Mar 30 #jQuery
如何编写jquery插件
Mar 29 #jQuery
jQuery日程管理控件glDatePicker用法详解
Mar 29 #jQuery
jQuery实现简单漂亮的Nav导航菜单效果
Mar 29 #jQuery
jQuery实现的手风琴侧边菜单效果
Mar 29 #jQuery
You might like
PHP使用strtotime计算两个给定日期之间天数的方法
2015/03/18 PHP
如何使用Gitblog和Markdown建自己的博客
2015/07/31 PHP
PHP文件后缀不强制为.php方法
2019/03/31 PHP
用JavaScript显示随机图像或引用
2009/04/21 Javascript
基于jquery的finkyUI插件与Ajax实现页面数据加载功能
2010/12/03 Javascript
node.js WEB开发中图片验证码的实现方法
2014/06/03 Javascript
JS运动框架之分享侧边栏动画实例
2015/03/03 Javascript
js简单实现点击左右运动的方法
2015/04/10 Javascript
jQuery插件之jQuery.Form.js用法实例分析(附demo示例源码)
2016/01/04 Javascript
详解Node.js模块间共享数据库连接的方法
2016/05/24 Javascript
AngularJS 应用身份认证的技巧总结
2016/11/07 Javascript
js实现表格筛选功能
2017/01/18 Javascript
JavaScript使用readAsDataUrl方法预览图片
2017/05/10 Javascript
layui之select的option叠加问题的解决方法
2018/03/08 Javascript
ES6与CommonJS中的模块处理的区别
2018/06/13 Javascript
详解微信小程序canvas圆角矩形的绘制的方法
2018/08/22 Javascript
使用npm命令提示: 'npm' 不是内部或外部命令,也不是可运行的程序的处理方法
2020/05/14 Javascript
uni-app使用微信小程序云函数的步骤示例
2020/05/22 Javascript
Vue Element校验validate的实例
2020/09/21 Javascript
详解如何在vue+element-ui的项目中封装dialog组件
2020/12/11 Vue.js
[53:44]DOTA2-DPC中国联赛 正赛 PSG.LGD vs Magma BO3 第一场 1月31日
2021/03/11 DOTA
介绍Python中的fabs()方法的使用
2015/05/14 Python
Pyinstaller将py打包成exe的实例
2018/03/31 Python
Python3.7中安装openCV库的方法
2018/07/11 Python
Python数据类型之List列表实例详解
2019/05/08 Python
Madewell澳大利亚官方网站:美国休闲服饰品牌
2019/07/18 全球购物
门诊挂号室室长岗位职责
2013/11/27 职场文书
大学辅导员事迹材料
2014/02/05 职场文书
书香家庭事迹材料
2014/05/09 职场文书
民族学专业求职信
2014/07/28 职场文书
陈安之励志演讲稿
2014/08/21 职场文书
个人租房协议书(范本)
2014/10/14 职场文书
面试通知单大全
2015/04/20 职场文书
论文答辩开场白大全
2015/05/27 职场文书
导游词之临安白水涧
2019/11/05 职场文书
撤回我也能看到!教你用Python制作微信防撤回脚本
2021/06/11 Python