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插件FusionCharts绘制2D双折线图效果示例【附demo源码】
Apr 14 jQuery
基于jQuery和CSS3实现APPLE TV海报视差效果
Jun 16 jQuery
JQuery 获取Dom元素的实例讲解
Jul 08 jQuery
jQuery动态添加.active 实现导航效果代码思路详解
Aug 29 jQuery
利用jQuery实现简单的拖曳效果实例代码
Oct 20 jQuery
jquery如何实现点击空白处隐藏元素
Dec 05 jQuery
jquery.pagination.js分页使用教程
Oct 23 jQuery
jQuery实现每日秒杀商品倒计时功能
Sep 06 jQuery
JQuery使用属性addClass、removeClass和toggleClass实现增加和删除类操作示例
Nov 18 jQuery
viewer.js一个强大的基于jQuery的图像查看插件(支持旋转、缩放)
Apr 01 jQuery
JavaScript或jQuery 获取option value值方法解析
May 12 jQuery
jQuery HTML获取内容和属性操作实例分析
May 20 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 创建以UNIX时间戳命名的文件夹(示例代码)
2014/03/08 PHP
php使用ereg验证文件上传的方法
2014/12/16 PHP
php利用smtp类实现电子邮件发送
2015/10/30 PHP
php基于ob_start(ob_gzhandler)实现网页压缩功能的方法
2017/02/18 PHP
TP(thinkPHP)框架多层控制器和多级控制器的使用示例
2018/06/13 PHP
php生成微信红包数组的方法
2019/09/05 PHP
自己开发Dojo的建议框架
2008/09/24 Javascript
jQuery调用WebService的实现代码
2011/06/19 Javascript
20款非常优秀的 jQuery 工具提示插件 推荐
2012/07/15 Javascript
JS简单实现登陆验证附效果图
2013/11/19 Javascript
JS短路原理的应用示例 精简代码的途径
2013/12/13 Javascript
防止登录页面出现在frame中js代码
2014/07/22 Javascript
JS判断变量是否为空判断是否null
2014/07/25 Javascript
常用javascript表单验证汇总
2020/07/20 Javascript
基于jquery实现动态竖向柱状条特效
2016/02/12 Javascript
Javascript的无new构建实例详解
2016/05/15 Javascript
如何使用jquery实现文字上下滚动效果
2016/10/12 Javascript
开源免费天气预报接口API及全国所有地区代码(国家气象局提供)
2016/12/26 Javascript
微信小程序实现折叠展开效果
2018/07/19 Javascript
vue中利用Promise封装jsonp并调取数据
2019/06/18 Javascript
nodejs中各种加密算法的实现详解
2019/07/11 NodeJs
jQuery单页面文字搜索插件jquery.fullsearch.js的使用方法
2020/02/04 jQuery
功能完善的小程序日历组件的实现
2020/03/31 Javascript
python中使用百度音乐搜索的api下载指定歌曲的lrc歌词
2014/07/18 Python
HTML5中form如何关闭自动完成功能的方法
2018/07/02 HTML / CSS
eBay英国购物网站:eBay.co.uk
2019/06/19 全球购物
我有一个char * 型指针正巧指向一些int 型变量, 我想跳过它们。 为什么如下的代码((int *)p)++; 不行?
2013/05/09 面试题
教师竞聘演讲稿
2014/05/16 职场文书
面试必备的求职信
2014/05/25 职场文书
工作检讨书大全
2015/01/26 职场文书
学校三八妇女节活动总结
2015/02/06 职场文书
小学运动会入场词
2015/07/18 职场文书
班主任工作经验交流会总结
2015/11/02 职场文书
导游词之广州陈家祠
2019/10/21 职场文书
Nginx Rewrite使用场景及配置方法解析
2021/04/01 Servers
Python编程super应用场景及示例解析
2021/10/05 Python