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和原生JavaScript实现网页定位导航特效
Apr 03 jQuery
jquery.validate表单验证插件使用详解
Jun 21 jQuery
jQuery上传插件webupload使用方法
Aug 01 jQuery
深入研究jQuery图片懒加载 lazyload.js使用方法
Aug 16 jQuery
jquery.rotate.js实现可选抽奖次数和中奖内容的转盘抽奖代码
Aug 23 jQuery
jQueryUI Sortable 应用Demo(分享)
Sep 07 jQuery
jQuery判断网页是否已经滚动到浏览器底部的实现方法
Oct 27 jQuery
jQuery选择器之层次选择器用法实例分析
Feb 19 jQuery
简单易扩展可控性强的Jquery转盘抽奖程序
Mar 16 jQuery
如何用webpack4.0撸单页/多页脚手架 (jquery, react, vue, typescript)
Jun 18 jQuery
jquery实现弹窗(系统提示框)效果
Dec 10 jQuery
JQuery使用数组遍历跳出each循环
Sep 01 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 禁止页面缓存输出
2009/01/07 PHP
php 接口类与抽象类的实际作用
2009/11/26 PHP
PHP GD 图像处理组件的常用函数总结
2010/04/28 PHP
thinkPHP5.0框架整体架构总览【应用,模块,MVC,驱动,行为,命名空间等】
2017/03/25 PHP
在PHP中输出JS语句以及乱码问题的解决方案
2019/02/13 PHP
浅谈laravel5.5 belongsToMany自身的正确用法
2019/10/17 PHP
thinkphp框架类库扩展操作示例
2019/11/26 PHP
学习YUI.Ext 第七天--关于View&amp;JSONView
2007/03/10 Javascript
让div层随鼠标移动的实现代码 ie ff
2009/12/18 Javascript
javascript之Partial Application学习
2013/01/10 Javascript
JS delegate与live浅析
2013/12/21 Javascript
老生常谈遮罩层 滚动条的问题
2016/04/29 Javascript
jQuery的each循环用法简单示例
2016/06/12 Javascript
BootStrap 智能表单实战系列(二)BootStrap支持的类型简介
2016/06/13 Javascript
jQuery on()方法绑定动态元素的点击事件无响应的解决办法
2016/07/07 Javascript
JavaScript比较当前时间是否在指定时间段内的方法
2016/08/02 Javascript
最实用的JS数组函数整理
2017/12/05 Javascript
vue指令只能输入正数并且只能输入一个小数点的方法
2018/06/08 Javascript
nodejs微信开发之授权登录+获取用户信息
2019/03/17 NodeJs
Python配置文件解析模块ConfigParser使用实例
2015/04/13 Python
详解Python中的相对导入和绝对导入
2017/01/06 Python
python实现杨辉三角思路
2017/07/14 Python
ubuntu安装sublime3并配置python3环境的方法
2018/03/15 Python
python监测当前联网状态并连接的实例
2018/12/18 Python
TensorFlow命名空间和TensorBoard图节点实例
2020/01/23 Python
python3实现raspberry pi(树莓派)4驱小车控制程序
2020/02/12 Python
Django微信小程序后台开发教程的实现
2020/06/03 Python
python如何建立全零数组
2020/07/19 Python
阿玛尼化妆品美国官网:Giorgio Armani Beauty
2017/02/02 全球购物
EQVVS官网:设计师男装和女装
2018/10/24 全球购物
Vans(范斯)新西兰官方网站:美国原创极限运动品牌
2020/09/19 全球购物
大学生工作求职信
2014/06/23 职场文书
个人股份转让协议书范本
2014/10/26 职场文书
2015年清明节扫墓演讲稿
2015/03/18 职场文书
基层工作经历证明
2015/06/19 职场文书
GoFrame基于性能测试得知grpool使用场景
2022/06/21 Golang