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插件Echarts实现的渐变色柱状图
Mar 23 jQuery
jQuery编写textarea输入字数限制代码
Mar 23 jQuery
jquery.uploadifive插件怎么解决上传限制图片或文件大小问题
May 08 jQuery
jQuery选取所有复选框被选中的值并用Ajax异步提交数据的实例
Aug 04 jQuery
jQuery实现html双向绑定功能示例
Oct 09 jQuery
jQuery实现的简单无刷新评论功能示例
Nov 08 jQuery
jquery ajaxfileupload异步上传插件
Nov 21 jQuery
jQuery NProgress.js加载进度插件的简单使用方法
Jan 31 jQuery
Vue.js 通过jQuery ajax获取数据实现更新后重新渲染页面的方法
Aug 09 jQuery
vue-cli 引入jQuery,Bootstrap,popper的方法
Sep 03 jQuery
jQuery表单选择器用法详解
Aug 22 jQuery
jquery插件实现轮播图效果
Oct 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
点评山进PR-D3L三波段收音机
2021/03/02 无线电
PHP 和 MySQL 开发的 8 个技巧
2007/01/02 PHP
解决MySQL中文输出变成问号的问题
2008/06/05 PHP
浅析PKI加密解密 OpenSSL
2013/07/01 PHP
javascript中的array数组使用技巧
2010/01/31 Javascript
扩展jquery实现客户端表格的分页、排序功能代码
2011/03/16 Javascript
javascript中的void运算符语法及使用介绍
2013/03/10 Javascript
表单序列化与jq中的serialize使用示例
2014/02/21 Javascript
jquery实现文字单行横移或翻转(上下、左右跳转)
2017/01/08 Javascript
JavaScript 自定义事件之我见
2017/09/25 Javascript
JavaScript 中使用 Generator的方法
2017/12/29 Javascript
select标签设置默认选中的选项方法
2018/03/02 Javascript
vue路由懒加载的实现方法
2018/03/12 Javascript
setTimeout时间设置为0详细解析
2018/03/13 Javascript
vue实现个人信息查看和密码修改功能
2018/05/06 Javascript
vue使用jsonp抓取qq音乐数据的方法
2018/06/21 Javascript
JavaScript引用类型RegExp基本用法详解
2018/08/09 Javascript
JS浅拷贝和深拷贝原理与实现方法分析
2019/02/28 Javascript
小程序新版订阅消息模板消息
2019/12/31 Javascript
Javascript操作select控件代码实例
2020/02/14 Javascript
[04:45]上海特级锦标赛主赛事第三日TOP10
2016/03/05 DOTA
python和C语言混合编程实例
2014/06/04 Python
Python 搭建Web站点之Web服务器网关接口
2016/11/06 Python
详解python中的 is 操作符
2017/12/26 Python
python使用matplotlib绘制热图
2018/11/07 Python
python中bytes和str类型的区别
2019/10/21 Python
Python 制作查询商品历史价格的小工具
2020/10/20 Python
荷兰睡眠专家:Beter Bed
2020/11/23 全球购物
仓库班组长岗位职责
2013/12/12 职场文书
网站美工岗位职责
2014/04/02 职场文书
班长竞选演讲稿
2014/04/24 职场文书
计算机专业自荐信
2014/05/24 职场文书
传播学专业毕业生自荐书
2014/07/01 职场文书
解放思想大讨论活动总结
2015/05/09 职场文书
2015年幼儿园班主任个人工作总结
2015/10/22 职场文书
flex布局中使用flex-wrap实现换行的项目实践
2022/06/21 HTML / CSS