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 10 jQuery
jQuery实现拼图小游戏(实例讲解)
Jul 24 jQuery
jquery中done和then的区别(详解)
Dec 19 jQuery
jQuery中的类名选择器(.class)用法简单示例
May 14 jQuery
jQuery实现下拉菜单动态添加数据点击滑出收起其他功能
Jun 14 jQuery
jQuery选择器之基本选择器用法实例分析
Feb 19 jQuery
jquery简单实现纵向的无缝滚动代码实例
Apr 01 jQuery
jQuery实现条件搜索查询、实时取值及升降序排序的方法分析
May 04 jQuery
jquery+php后台实现省市区联动功能示例
May 23 jQuery
jQuery实现每日秒杀商品倒计时功能
Sep 06 jQuery
jquery validate 实现动态增加/删除验证规则操作示例
Oct 28 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限制上传文件类型并保存上传文件的方法
2015/03/13 PHP
php文件压缩之PHPZip类用法实例
2015/06/18 PHP
PHP设计模式之工厂模式实例总结
2017/09/01 PHP
js不能获取隐藏的div的宽度只能先显示后获取
2014/09/04 Javascript
JavaScript函数详解
2015/02/27 Javascript
JS仿hao123导航页面图片轮播效果
2016/09/01 Javascript
详解Node.js access_token的获取、存储及更新
2017/06/20 Javascript
Vue 动态设置路由参数的案例分析
2018/04/24 Javascript
vue.js使用v-if实现显示与隐藏功能示例
2018/07/06 Javascript
vue实现商品加减计算总价的实例代码
2018/08/12 Javascript
JavaScript使用ul中li标签实现删除效果
2019/04/15 Javascript
[45:38]DOTA2上海特级锦标赛主赛事日 - 1 胜者组第一轮#1Liquid VS Alliance第一局
2016/03/02 DOTA
解决uWSGI的编码问题详解
2017/03/24 Python
Python基于ThreadingTCPServer创建多线程代理的方法示例
2018/01/11 Python
python3实现基于用户的协同过滤
2018/05/31 Python
python实现图片筛选程序
2018/10/24 Python
对python中不同模块(函数、类、变量)的调用详解
2019/07/16 Python
python虚拟环境完美部署教程
2019/08/06 Python
python实现通过flask和前端进行数据收发
2019/08/22 Python
Django框架HttpResponse对象用法实例分析
2019/11/01 Python
python实现遍历文件夹图片并重命名
2020/03/23 Python
pycharm Tab键设置成4个空格的操作
2021/02/26 Python
Bench加拿大官方网站:英国城市服装品牌
2017/11/03 全球购物
测绘工程专业个人自我评价
2013/12/01 职场文书
建筑项目策划书
2014/01/13 职场文书
大学生职业规划书的范本
2014/02/18 职场文书
保险经纪人求职信
2014/03/11 职场文书
利群广告词
2014/03/20 职场文书
护士长竞聘书
2014/03/31 职场文书
甜品蛋糕店创业计划书
2014/09/21 职场文书
年度考核表个人总结
2015/03/06 职场文书
试用期解除劳动合同通知书
2015/04/16 职场文书
使用python如何删除同一文件夹下相似的图片
2021/05/07 Python
python字符串的多行输出的实例详解
2021/06/08 Python
Linux中如何安装并部署Redis
2022/04/18 Servers
详解SQL报错盲注
2022/07/23 SQL Server