jQuery源码阅读(八)---jQuery中的继承extend

2024-05-04 14:18

本文主要是介绍jQuery源码阅读(八)---jQuery中的继承extend,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

今天看了jQuery源码中关于extend函数的部分,这部分就相当于jQuery继承,后面在整理的过程中说明如何继承。
还是跟之前的分析方法一样,要分析一个函数的实现,首先得知道函数是干什么的,它的功能是啥。

extend方法应用

扩展插件

在jQuery的学习当中,我们学过如何去写一个插件,而且插件分全局插件和实例插件,即一种是直接挂载在jQuery上的,另一种是挂载在jQuery实例对象上的。
比如下面两种实现:
扩展全局插件:

$.extend({add: function(a, b){return a + b;}
});
$.add(4,9);           //返回13

对象插件:

$.fn.extend({add : function(a, b){return a + b;}
})
$().add(2,8)            //返回10

扩展对象

这也可以算是jQuery中实现继承的一种方式。

a = {name : 'liu'
}
b = {name: 'yang'
}
var res = $.extend(a, b)  
//res可以说是继承了a和b的属性和方法
默认浅拷贝,改变a.name不会影响b.nameaa = {name: {age: 20}
}
bb = {name: {age: 15}
}
$.extend(aa, bb)
//浅拷贝,只拷贝对象,不会把内部具体的属性也拷贝
//所以修改a.name.age会改变b.name.age
aa.name.age = 30;
//此时bb.name.age也是30//如果改用深拷贝的话
$.extend(true, aa, bb)
//aa和bb中的name是不同的对象,指向不同的内存区域
//因此改变aa.name.age不会影响bb.name.age

extend方法在扩展对象时,最前面可以传一个布尔值的参数true,表示扩展对象时使用深拷贝,即将所有层级的对象属性都进行拷贝。而不加布尔值的参数,则默认是浅拷贝,即不会复制内层级的属性和方法。

extend源码分析

jQuery.extend = jQuery.fn.extend = function() {};

首先,我想说的是 jQuery.extend和jQuery.fn.extend是同一份代码,也就是说 实现思路是一样的.那如何才能确定是在jQuery上扩展的,还是在jQuery实例对象上扩展的?

JS中有个this的概念,即指向当前的上下文。具体点来说.

//直接调用函数时
function a(){return this;
}a();                //返回的是window对象

这里写图片描述

//如果通过对象调函数
var obj = {b: function(){return this;}
}
obj.b();            //返回的是Object对象

这里写图片描述

所以如果$.extend(),this指向的是jQuery;,如果$.fn.extend()this指向jQuery.fn也就是jQuery.prototype,那么在原型上扩展一个方法,就相当于在jQuery实例中可以调用该方法,从而实现扩展的目的。

接着下面的源码:

    var options, name, src, copy, copyIsArray, clone,//从这块可以学习到,如果不确定函数中有多少个参数时,可以用arguments来访问。target = arguments[0] || {},//如果是深拷贝,target此时为true;//如果不是,target此时是要扩展的第一个参数;i = 1,length = arguments.length,deep = false;// 深拷贝的情况if ( typeof target === "boolean" ) {deep = target;target = arguments[1] || {};// 跳过true和要扩展的第一个参数i = 2;}//如果不是对象,不是函数,target设为空对象,以便和后面对象能够合并if ( typeof target !== "object" && !jQuery.isFunction(target) ) {target = {};}//如果只有一个参数,那么就认为这是扩展插件,所以target就是this对象。前面也讲了什么情况下,this是jQuery,什么情况下this是jQuery.fnif ( length === i ) {target = this;--i;     //这个时候就从第一个参数开始处理}for ( ; i < length; i++ ) {//如果是对象扩展并且是浅拷贝,那么i从1开始//如果是对象扩展并且是深拷贝,那么i从2开始//如果是插件扩展,那么i从0开始//前面已经处理好了if ( (options = arguments[ i ]) != null ) {for ( name in options ) {src = target[ name ];copy = options[ name ];//注意这部分,下面会讲到if ( target === copy ) {continue;}//如果是深拷贝,那么对象内层的每一级属性都要拷贝,所以是一个递归的过程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 themtarget[ name ] = jQuery.extend( deep, clone, copy );} else if ( copy !== undefined ) {//如果不是深拷贝,就直接将name属性加到target对象里面了target[ name ] = copy;}}}}//最后返回扩展后的target对象;或者返回jQuery或者返回jQuery.fnreturn target;

下来缕一缕上面提到的

if ( target === copy ) {continue;
}

比如这么一种情况:

var obj = {age : 20
}
var obj1 = {age: obj
}
var res = $.extend(obj, obj1);

这种情况下,在extend函数内部,target为 obj = { age : 20 }, copy = options[‘age’] = obj = { age : 20 }
所以判断target和copy相等,就会continue,跳过该次循环,那为什么要这样做呢?
我们先把if ( target === copy ) { continue; }注释掉,看结果是什么?
这里写图片描述
可以看到,返回的是一个含有一个name属性的对象,而name属性又指向该对象,这样无限循环下去了。为什么会出现这种情况呢?
因为如果去掉continue的话,会继续后面的执行,即

target[ name ] = copy;

在这句执行之前,target指向一个Object对象,copy也是指向该对象,那么对target的修改也会影响copy对象,所以target.name修改为copy,相当于copy.name也修改为copy,这样就形成了无限循环的对象,这样实际上没有什么意义,所以jQuery避免了这种情况。可见,jQuery各方面的考虑是非常全面。希望能学到更多,理解更深刻!

这篇关于jQuery源码阅读(八)---jQuery中的继承extend的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/959397

相关文章

CSS3 布局样式及其应用举例

《CSS3布局样式及其应用举例》CSS3的布局特性为前端开发者提供了无限可能,无论是Flexbox的一维布局还是Grid的二维布局,它们都能够帮助开发者以更清晰、简洁的方式实现复杂的网页布局,本文给... 目录深入探讨 css3 布局样式及其应用引言一、CSS布局的历史与发展1.1 早期布局的局限性1.2

使用animation.css库快速实现CSS3旋转动画效果

《使用animation.css库快速实现CSS3旋转动画效果》随着Web技术的不断发展,动画效果已经成为了网页设计中不可或缺的一部分,本文将深入探讨animation.css的工作原理,如何使用以及... 目录1. css3动画技术简介2. animation.css库介绍2.1 animation.cs

CSS引入方式和选择符的讲解和运用小结

《CSS引入方式和选择符的讲解和运用小结》CSS即层叠样式表,是一种用于描述网页文档(如HTML或XML)外观和格式的样式表语言,它主要用于将网页内容的呈现(外观)和结构(内容)分离,从而实现... 目录一、前言二、css 是什么三、CSS 引入方式1、行内样式2、内部样式表3、链入外部样式表四、CSS 选

使用雪花算法产生id导致前端精度缺失问题解决方案

《使用雪花算法产生id导致前端精度缺失问题解决方案》雪花算法由Twitter提出,设计目的是生成唯一的、递增的ID,下面:本文主要介绍使用雪花算法产生id导致前端精度缺失问题的解决方案,文中通过代... 目录一、问题根源二、解决方案1. 全局配置Jackson序列化规则2. 实体类必须使用Long封装类3.

Nginx部署React项目时重定向循环问题的解决方案

《Nginx部署React项目时重定向循环问题的解决方案》Nginx在处理React项目请求时出现重定向循环,通常是由于`try_files`配置错误或`root`路径配置不当导致的,本文给大家详细介... 目录问题原因1. try_files 配置错误2. root 路径错误解决方法1. 检查 try_f

在React聊天应用中实现图片上传功能

《在React聊天应用中实现图片上传功能》在现代聊天应用中,除了文字和表情,图片分享也是一个重要的功能,本文将详细介绍如何在基于React的聊天应用中实现图片上传和预览功能,感兴趣的小伙伴跟着小编一起... 目录技术栈实现步骤1. 消息组件改造2. 图片预览组件3. 聊天输入组件改造功能特点使用说明注意事项

一文详解如何在Vue3中封装API请求

《一文详解如何在Vue3中封装API请求》在现代前端开发中,API请求是不可避免的一部分,尤其是与后端交互时,下面我们来看看如何在Vue3项目中封装API请求,让你在实现功能时更加高效吧... 目录为什么要封装API请求1. vue 3项目结构2. 安装axIOS3. 创建API封装模块4. 封装API请求

全解析CSS Grid 的 auto-fill 和 auto-fit 内容自适应

《全解析CSSGrid的auto-fill和auto-fit内容自适应》:本文主要介绍了全解析CSSGrid的auto-fill和auto-fit内容自适应的相关资料,详细内容请阅读本文,希望能对你有所帮助... css  Grid 的 auto-fill 和 auto-fit/* 父元素 */.gri

Python多重继承慎用的地方

《Python多重继承慎用的地方》多重继承也可能导致一些问题,本文主要介绍了Python多重继承慎用的地方,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面... 目录前言多重继承要慎用Mixin模式最后前言在python中,多重继承是一种强大的功能,它允许一个

Android实现一键录屏功能(附源码)

《Android实现一键录屏功能(附源码)》在Android5.0及以上版本,系统提供了MediaProjectionAPI,允许应用在用户授权下录制屏幕内容并输出到视频文件,所以本文将基于此实现一个... 目录一、项目介绍二、相关技术与原理三、系统权限与用户授权四、项目架构与流程五、环境配置与依赖六、完整