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

相关文章

Java汇编源码如何查看环境搭建

《Java汇编源码如何查看环境搭建》:本文主要介绍如何在IntelliJIDEA开发环境中搭建字节码和汇编环境,以便更好地进行代码调优和JVM学习,首先,介绍了如何配置IntelliJIDEA以方... 目录一、简介二、在IDEA开发环境中搭建汇编环境2.1 在IDEA中搭建字节码查看环境2.1.1 搭建步

React实现原生APP切换效果

《React实现原生APP切换效果》最近需要使用Hybrid的方式开发一个APP,交互和原生APP相似并且需要IM通信,本文给大家介绍了使用React实现原生APP切换效果,文中通过代码示例讲解的非常... 目录背景需求概览技术栈实现步骤根据 react-router-dom 文档配置好路由添加过渡动画使用

使用Vue.js报错:ReferenceError: “Vue is not defined“ 的原因与解决方案

《使用Vue.js报错:ReferenceError:“Vueisnotdefined“的原因与解决方案》在前端开发中,ReferenceError:Vueisnotdefined是一个常见... 目录一、错误描述二、错误成因分析三、解决方案1. 检查 vue.js 的引入方式2. 验证 npm 安装3.

vue如何监听对象或者数组某个属性的变化详解

《vue如何监听对象或者数组某个属性的变化详解》这篇文章主要给大家介绍了关于vue如何监听对象或者数组某个属性的变化,在Vue.js中可以通过watch监听属性变化并动态修改其他属性的值,watch通... 目录前言用watch监听深度监听使用计算属性watch和计算属性的区别在vue 3中使用watchE

python解析HTML并提取span标签中的文本

《python解析HTML并提取span标签中的文本》在网页开发和数据抓取过程中,我们经常需要从HTML页面中提取信息,尤其是span元素中的文本,span标签是一个行内元素,通常用于包装一小段文本或... 目录一、安装相关依赖二、html 页面结构三、使用 BeautifulSoup javascript

Vue3 的 shallowRef 和 shallowReactive:优化性能

大家对 Vue3 的 ref 和 reactive 都很熟悉,那么对 shallowRef 和 shallowReactive 是否了解呢? 在编程和数据结构中,“shallow”(浅层)通常指对数据结构的最外层进行操作,而不递归地处理其内部或嵌套的数据。这种处理方式关注的是数据结构的第一层属性或元素,而忽略更深层次的嵌套内容。 1. 浅层与深层的对比 1.1 浅层(Shallow) 定义

这15个Vue指令,让你的项目开发爽到爆

1. V-Hotkey 仓库地址: github.com/Dafrok/v-ho… Demo: 戳这里 https://dafrok.github.io/v-hotkey 安装: npm install --save v-hotkey 这个指令可以给组件绑定一个或多个快捷键。你想要通过按下 Escape 键后隐藏某个组件,按住 Control 和回车键再显示它吗?小菜一碟: <template

【 html+css 绚丽Loading 】000046 三才归元阵

前言:哈喽,大家好,今天给大家分享html+css 绚丽Loading!并提供具体代码帮助大家深入理解,彻底掌握!创作不易,如果能帮助到大家或者给大家一些灵感和启发,欢迎收藏+关注哦 💕 目录 📚一、效果📚二、信息💡1.简介:💡2.外观描述:💡3.使用方式:💡4.战斗方式:💡5.提升:💡6.传说: 📚三、源代码,上代码,可以直接复制使用🎥效果🗂️目录✍️

【前端学习】AntV G6-08 深入图形与图形分组、自定义节点、节点动画(下)

【课程链接】 AntV G6:深入图形与图形分组、自定义节点、节点动画(下)_哔哩哔哩_bilibili 本章十吾老师讲解了一个复杂的自定义节点中,应该怎样去计算和绘制图形,如何给一个图形制作不间断的动画,以及在鼠标事件之后产生动画。(有点难,需要好好理解) <!DOCTYPE html><html><head><meta charset="UTF-8"><title>06

JAVA智听未来一站式有声阅读平台听书系统小程序源码

智听未来,一站式有声阅读平台听书系统 🌟&nbsp;开篇:遇见未来,从“智听”开始 在这个快节奏的时代,你是否渴望在忙碌的间隙,找到一片属于自己的宁静角落?是否梦想着能随时随地,沉浸在知识的海洋,或是故事的奇幻世界里?今天,就让我带你一起探索“智听未来”——这一站式有声阅读平台听书系统,它正悄悄改变着我们的阅读方式,让未来触手可及! 📚&nbsp;第一站:海量资源,应有尽有 走进“智听