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使用unlock.js插件实现滑动解锁
Apr 04 jQuery
jquery.validate表单验证插件使用详解
Jun 21 jQuery
jQuery实现节点的追加、替换、删除、复制功能示例
Jul 11 jQuery
jQuery Datatable 多个查询条件自定义提交事件(推荐)
Aug 24 jQuery
jQuery实现表单动态添加数据并提交的方法
Jul 19 jQuery
vue-cli 引入jQuery,Bootstrap,popper的方法
Sep 03 jQuery
jQuery each和js forEach用法比较
Feb 27 jQuery
jQuery.parseJSON()函数详解
Feb 28 jQuery
jQuery 查找元素操作实例小结
Oct 02 jQuery
jquery使用echarts实现有向图可视化功能示例
Nov 25 jQuery
jQuery实现的解析本地 XML 文档操作示例
Apr 30 jQuery
基于JavaScript或jQuery实现网站夜间/高亮模式
May 30 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个人网站架设连环讲(二)
2006/10/09 PHP
PHP 面向对象 PHP5 中的常量
2010/05/05 PHP
php实现多张图片上传加水印技巧
2013/04/18 PHP
php提示Failed to write session data错误的解决方法
2014/12/17 PHP
利用PHP访问带有密码的Redis方法示例
2017/02/09 PHP
JS控制阿拉伯数字转为中文大写示例代码
2013/09/04 Javascript
js 使FORM表单的所有元素不可编辑的示例代码
2013/10/17 Javascript
JQuery中使用Ajax赋值给全局变量失败异常的解决方法
2014/08/18 Javascript
原生js制作简单的数字键盘
2015/04/24 Javascript
jQuery的position()方法详解
2015/07/19 Javascript
Jquery效果大全之制作电脑健康体检得分特效附源码下载
2015/11/02 Javascript
浅析node连接数据库(express+mysql)
2015/11/30 Javascript
微信小程序 Image API实例详解
2016/09/30 Javascript
JavaScript输入框字数实时统计更新
2017/06/17 Javascript
vue2.0与bootstrap3实现列表分页效果
2017/11/28 Javascript
JavaScript实现数值自动增加动画
2017/12/28 Javascript
微信小程序实现点击空白隐藏的方法示例
2019/08/13 Javascript
微信小程序移动拖拽视图-movable-view实例详解
2019/08/17 Javascript
JQuery发送ajax请求时中文乱码问题解决
2019/11/14 jQuery
在Django的URLconf中使用命名组的方法
2015/07/18 Python
Python使用multiprocessing实现一个最简单的分布式作业调度系统
2016/03/14 Python
使用selenium模拟登录解决滑块验证问题的实现
2019/05/10 Python
Python 实现毫秒级淘宝抢购脚本的示例代码
2019/09/16 Python
python 实现单通道转3通道
2019/12/03 Python
Python同时迭代多个序列的方法
2020/07/28 Python
Python importlib模块重载使用方法详解
2020/10/13 Python
html5中的input新属性range使用记录
2014/09/05 HTML / CSS
网吧收银员岗位职责
2013/12/14 职场文书
业务员简历自我评价
2014/03/06 职场文书
社团活动总结模板
2014/06/30 职场文书
环境卫生工作汇报材料
2014/10/28 职场文书
开展党的群众路线教育实践活动工作总结
2014/11/05 职场文书
经典导游欢迎词
2015/01/26 职场文书
大学生毕业个人总结
2015/02/15 职场文书
2015年科室工作总结
2015/04/10 职场文书
安全知识竞赛主持词
2015/06/30 职场文书