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实现html table行Tr的复制、删除、计算功能
Jul 10 jQuery
jQuery列表检索功能实现代码
Jul 17 jQuery
基于jQuery Ajax实现下拉框无刷新联动
Dec 06 jQuery
jquery实现楼层滚动效果
Jan 01 jQuery
实现jquery放大镜的两种方法
Feb 22 jQuery
jQuery获取随机颜色的实例代码
May 21 jQuery
jQuery插件Validation表单验证详解
May 26 jQuery
jQuery实现表单动态添加与删除数据操作示例
Jul 03 jQuery
jQuery实现table表格checkbox全选的方法分析
Jul 04 jQuery
详解如何使用webpack打包多页jquery项目
Feb 01 jQuery
jquery.tagsinput.js实现记录checkbox勾选的顺序
Sep 21 jQuery
深入分析jQuery.one() 函数
Jun 03 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 网络开发详解之远程文件包含漏洞
2010/04/25 PHP
php简单日历函数
2015/10/28 PHP
php实现scws中文分词搜索的方法
2015/12/25 PHP
WordPress开发中用于获取近期文章的PHP函数使用解析
2016/01/05 PHP
PHP实现微信对账单处理
2018/10/01 PHP
document 和 document.all 分别什么时候用
2006/06/22 Javascript
xml和web特殊字符
2009/04/28 Javascript
一步一步教你写一个jQuery的插件教程(Plugin)
2009/09/03 Javascript
js和jquery批量绑定事件传参数一(新猪猪原创)
2010/06/23 Javascript
JavaScript高级程序设计 客户端存储学习笔记
2011/09/10 Javascript
js实现局部页面打印预览原理及示例代码
2014/07/03 Javascript
jquery通过扩展select控件实现支持enter或focus选择的方法
2015/11/19 Javascript
jQuery+CSS实现滑动的标签分栏切换效果
2015/12/17 Javascript
js面向对象的写法
2016/02/19 Javascript
解读Bootstrap v4 sass设计
2016/05/29 Javascript
xmlplus组件设计系列之网格(DataGrid)(10)
2017/05/05 Javascript
vue-resouce设置请求头的三种方法
2017/09/12 Javascript
nuxt+axios解决前后端分离SSR的示例代码
2017/10/24 Javascript
Bootstrap Table中的多选框删除功能
2018/07/15 Javascript
Vue CLI3 开启gzip压缩文件的方式
2018/09/30 Javascript
微信小程序清空输入框信息与实现屏幕往上滚动的示例代码
2020/06/23 Javascript
Python类的专用方法实例分析
2015/01/09 Python
python中threading超线程用法实例分析
2015/05/16 Python
基于Django框架利用Ajax实现点赞功能实例代码
2018/08/19 Python
Python读写zip压缩文件的方法
2018/08/29 Python
Python flask框架post接口调用示例
2019/07/03 Python
Django将默认的SQLite更换为MySQL的实现
2019/11/18 Python
Python新手如何理解循环加载模块
2020/05/29 Python
HTML5的自定义属性data-*详细介绍和JS操作实例
2014/04/10 HTML / CSS
你们项目是如何进行变更控制的
2015/08/26 面试题
军神教学反思
2014/02/04 职场文书
合作协议书范本
2014/04/17 职场文书
材料化学专业求职信
2014/07/15 职场文书
故宫导游词
2015/01/31 职场文书
拉贝日记观后感
2015/06/05 职场文书
2015中学政教处工作总结
2015/07/22 职场文书