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中的deferred使用方法
Mar 27 jQuery
jQuery动态追加页面数据以及事件委托详解
May 06 jQuery
jQuery实现可编辑表格并生成json结果(实例代码)
Jul 19 jQuery
jQuery实现手势解锁密码特效
Aug 14 jQuery
利用JQuery操作iframe父页面、子页面的元素和方法汇总
Sep 10 jQuery
jquery动态添加以及遍历option并获取特定样式名称的option方法
Jan 29 jQuery
手写简单的jQuery雪花飘落效果实例
Apr 22 jQuery
jQuery滑动效果实现方法分析
Sep 05 jQuery
jQuery子选择器与可见性选择器实例分析
Jun 28 jQuery
jquery分页优化操作实例分析
Aug 23 jQuery
JavaScript自动生成 年月范围 选择功能完整示例【基于jQuery插件】
Sep 03 jQuery
jQuery 选择方法及$(this)用法实例分析
May 19 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 SQLite类
2009/05/07 PHP
js 鼠标拖动对象 可让任何div实现拖动效果
2009/11/09 Javascript
跟着JQuery API学Jquery 之二 属性
2010/04/09 Javascript
Angularjs 基础入门
2014/12/26 Javascript
JS实现的生成随机数的4个函数分享
2015/02/11 Javascript
JS动态修改iframe内嵌网页地址的方法
2015/04/01 Javascript
javascript实现禁止鼠标滚轮事件
2015/07/24 Javascript
谈一谈jQuery核心架构设计
2016/03/28 Javascript
基于javascript实现tab选项卡切换特效调试笔记
2016/03/30 Javascript
在localStorage中存储对象数组并读取的方法
2016/09/24 Javascript
JavaScript实现水平进度条拖拽效果
2017/01/18 Javascript
vue进行图片的预加载watch用法实例讲解
2018/02/07 Javascript
vue 点击按钮增加一行的方法
2018/09/07 Javascript
JavaScript 禁止用户保存图片的实现代码
2020/04/28 Javascript
JS继承实现方法及优缺点详解
2020/09/02 Javascript
小程序实现tab标签页
2020/11/16 Javascript
python将xml xsl文件生成html文件存储示例讲解
2013/12/03 Python
python读写ini文件示例(python读写文件)
2014/03/25 Python
python实现TCP服务器端与客户端的方法详解
2015/04/30 Python
python开发之thread实现布朗运动的方法
2015/11/11 Python
Python实现字典依据value排序
2016/02/24 Python
python多线程socket编程之多客户端接入
2017/09/12 Python
Python简单实现控制电脑的方法
2018/01/22 Python
Python Pillow Image Invert
2019/01/22 Python
基于python求两个列表的并集.交集.差集
2020/02/10 Python
python 读取、写入txt文件的示例
2020/09/27 Python
伯克斯奥特莱斯:Burkes Outlet
2019/03/30 全球购物
Coccinelle官网:意大利的著名皮具品牌
2019/05/15 全球购物
酒店营销策划方案
2014/02/07 职场文书
意向书范文
2014/03/31 职场文书
本科毕业生求职信
2014/06/15 职场文书
教师党的群众路线教育实践活动个人整改方案
2014/10/31 职场文书
求职简历自荐信怎么写
2015/03/26 职场文书
村官2015年度工作总结
2015/10/14 职场文书
如何用threejs实现实时多边形折射
2021/05/07 Javascript
Win11黑色桌面背景怎么办?Win11黑色壁纸解决方法汇总
2022/04/05 数码科技