jQuery技术内幕:深入解析jQuery架构设计与实现原理. 2.6 jQuery.extend()、jQuery.fn.extend()

本文涉及的产品
云解析 DNS,旗舰版 1个月
全局流量管理 GTM,标准版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
简介:

2.6 jQuery.extend()、jQuery.fn.extend()

2.6.1 如何使用

方法jQuery.extend()和jQuery.fn.extend()用于合并两个或多个对象的属性到第一个对象,它们的语法如下:

jQuery.extend( [deep], target, object1 [, objectN] )

jQuery.fn.extend( [deep], target, object1 [, objectN] )

其中,参数deep是可选的布尔值,表示是否进行深度合并(即递归合并)。合并行为默认是不递归的,如果第一个参数的属性本身是一个对象或数组,它会被第二个或后面的其他参数的同名属性完全覆盖。如果为true,表示进行深度合并,合并过程是递归的。

参数target是目标对象;参数object1和objectN是源对象,包含了待合并的属性。如果提供了两个或更多的对象,所有源对象的属性将会合并到目标对象;如果仅提供一个对象,意味着参数target被忽略,jQuery或jQuery.fn被当作目标对象,通过这种方式可以在jQuery或jQuery.fn上添加新的属性和方法,jQuery的其他模块大都是这么实现的。

方法jQuery.extend()和jQuery.fn.extend()常用于编写插件和处理函数的参数。

2.6.2 源码分析

方法jQuery.extend()和jQuery.fn.extend()执行的关键步骤如下所示:

1)修正参数deep、target、源对象的起始下标。

2)逐个遍历源对象:

a.?遍历源对象的属性。

b.?覆盖目标对象的同名属性;如果是深度合并,则先递归调用jQuery.extend()。

下面分析方法jQuery.extend()和jQuery.fn.extend()的源码。

1.?定义jQuery.extend()和jQuery.fn.extend()

相关代码如下所示:

324 jQuery.extend = jQuery.fn.extend = function() {

第324行:因为参数的个数是不确定的,可以有任意多个,所以没有列出可接受的参数。

2.?定义局部变量

相关代码如下所示:

325     var options, name, src, copy, copyIsArray, clone,

326         target = arguments[0] || {},

327         i = 1,

328         length = arguments.length,

329         deep = false;

330

第325~329行:定义一组局部变量,它们的含义和用途如下:

变量options:指向某个源对象。

变量name:表示某个源对象的某个属性名。

变量src:表示目标对象的某个属性的原始值。

变量copy:表示某个源对象的某个属性的值。

变量copyIsArray:指示变量copy是否是数组。

变量clone:表示深度复制时原始值的修正值。

变量target:指向目标对象。

变量i:表示源对象的起始下标。

变量length:表示参数的个数,用于修正变量target。

变量deep:指示是否执行深度复制,默认为false。

3.?修正目标对象target、源对象起始下标i

相关代码如下所示:

331     // Handle a deep copy situation

332     if ( typeof target === "boolean" ) {

333         deep = target;

334         target = arguments[1] || {};

335         // skip the boolean and the target

336         i = 2;

337     }

338

339     // Handle case when target is a string or something (possible in deep copy)

340     if ( typeof target !== "object" && !jQuery.isFunction(target) ) {

341         target = {};

342     }

343

344     // extend jQuery itself if only one argument is passed

345     if ( length === i ) {

346         target = this;

347         --i;

348     }

349

第331~337行:如果第一个参数是布尔值,则修正第一个参数为 deep,修正第二个参数为目标对象 target,并且期望源对象从第三个元素开始。

变量i的初始值为1,表示期望源对象从第2个元素开始;当第一个参数为布尔型时,变量i变为2,表示期望源对象从第3个元素开始。

第339~342行:如果目标对象target不是对象、不是函数,而是一个字符串或其他的基本类型,则统一替换为空对象{},因为在基本类型上设置非原生属性是无效的。例如:

var s = 'hi';

s.test = 'hello';

console.log( s.test );        // 打印undefined

第344~348行:变量i表示源对象开始的下标,变量length表示参数个数,如果二者相等,表示期望的源对象没有传入,则把jQuery或jQuery.fn作为目标对象,并且把源对象的开始下标减一,从而使得传入的对象被当作源对象。变量length等于i可能有两种情况:

extend( object ),只传入了一个参数。

extend( deep, object ),传入了两个参数,第一个参数是布尔值。

4.?逐个遍历源对象

相关代码如下所示:

350     for ( ; i < length; i++ ) {

第350行:循环变量i表示源对象开始的下标,很巧妙的用法。

(1)遍历源对象的属性

下面的代码用于遍历源对象的属性:

351         // Only deal with non-null/undefined values

352         if ( (options = arguments[ i ]) != null ) {

353             // Extend the base object

354             for ( name in options ) {

第352行:arguments是一个类似数组的对象,包含了传入的参数,可以通过整型下标访问指定位置的参数。这行代码把获取源对象和对源对象的判断合并为一条语句,只有源对象不是null、undefined时才会继续执行。

第353行:开始遍历单个源对象的属性。

(2)覆盖目标对象的同名属性

相关代码如下所示:

355                 src = target[ name ];

356                 copy = options[ name ];

357

358                 // Prevent never-ending loop

359                 if ( target === copy ) {

360                     continue;

361                 }

362

363                 // Recurse if we're merging plain objects or arrays

364                if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) {

365                     if ( copyIsArray ) {

366                         copyIsArray = false;

367                         clone = src && jQuery.isArray(src) ? src : [];

368

369                     } else {

370                         clone = src && jQuery.isPlainObject(src) ? src : {};

371                     }

372

373                     // Never move original objects, clone them

374                     target[ name ] = jQuery.extend( deep, clone, copy );

375

376                 // Don't bring in undefined values

377                 } else if ( copy !== undefined ) {

378                     target[ name ] = copy;

379                 }

380             }

381         }

382     }

383

第355~361行:变量src是原始值,变量copy是复制值。如果复制值copy与目标对象target相等,为了避免深度遍历时死循环,因此不会覆盖目标对象的同名属性。如果注释掉第360行,下面的代码会抛出堆栈溢出异常:

var o = {};

o.n1 = o;

$.extend( true, o, { n2: o } );

// 抛出异常:

// Uncaught RangeError: Maximum call stack size exceeded

注意,判断target === copy时使用的是“===”,强制不做类型转换;如果使用“==”,则可能因自动类型转换而导致错误。

第364~374行:如果是深度合并,且复制值copy是普通JavaScript对象或数组,则递归合并。

第365~371行:复制值copy是数组时,如果原始值src不是数组,则修正为空数组;复制值copy是普通JavaScript对象时,如果原始值src不是普通JavaScript对象,则修正为空对象{}。把原始值src或修正后的值赋值给原始值副本clone。

通过调用方法jQuery.isPlainObject( copy )判断复制值copy是否是“纯粹”的JavaScript对象,只有通过对象直接量{}或new Object()创建的对象,才会返回true。例如:

jQuery.isPlainObject( { hello: 'world' } );  // true

jQuery.isPlainObject( new Object() );                // true

jQuery.isPlainObject( new Object(1) );              // true

方法jQuery.isPlainObject()将在2.8.2节介绍和分析。

第374行:先把复制值copy递归合并到原始值副本clone中,然后覆盖目标对象的同名属性。

第376~379行:如果不是深度合并,并且复制值copy不是undefined,则直接覆盖目标对象的同名属性。

相关文章
|
27天前
|
存储 缓存 算法
HashMap深度解析:从原理到实战
HashMap,作为Java集合框架中的一个核心组件,以其高效的键值对存储和检索机制,在软件开发中扮演着举足轻重的角色。作为一名资深的AI工程师,深入理解HashMap的原理、历史、业务场景以及实战应用,对于提升数据处理和算法实现的效率至关重要。本文将通过手绘结构图、流程图,结合Java代码示例,全方位解析HashMap,帮助读者从理论到实践全面掌握这一关键技术。
77 13
|
28天前
|
存储 SQL 关系型数据库
MySQL进阶突击系列(03) MySQL架构原理solo九魂17环连问 | 给大厂面试官的一封信
本文介绍了MySQL架构原理、存储引擎和索引的相关知识点,涵盖查询和更新SQL的执行过程、MySQL各组件的作用、存储引擎的类型及特性、索引的建立和使用原则,以及二叉树、平衡二叉树和B树的区别。通过这些内容,帮助读者深入了解MySQL的工作机制,提高数据库管理和优化能力。
|
1月前
|
人工智能 前端开发 编译器
【AI系统】LLVM 架构设计和原理
本文介绍了LLVM的诞生背景及其与GCC的区别,重点阐述了LLVM的架构特点,包括其组件独立性、中间表示(IR)的优势及整体架构。通过Clang+LLVM的实际编译案例,展示了从C代码到可执行文件的全过程,突显了LLVM在编译器领域的创新与优势。
73 3
|
2月前
|
运维 持续交付 云计算
深入解析云计算中的微服务架构:原理、优势与实践
深入解析云计算中的微服务架构:原理、优势与实践
85 1
|
1天前
|
Java Linux C语言
《docker基础篇:2.Docker安装》包括前提说明、Docker的基本组成、Docker平台架构图解(架构版)、安装步骤、阿里云镜像加速、永远的HelloWorld、底层原理
《docker基础篇:2.Docker安装》包括前提说明、Docker的基本组成、Docker平台架构图解(架构版)、安装步骤、阿里云镜像加速、永远的HelloWorld、底层原理
156 88
|
2天前
|
机器学习/深度学习 自然语言处理 搜索推荐
自注意力机制全解析:从原理到计算细节,一文尽览!
自注意力机制(Self-Attention)最早可追溯至20世纪70年代的神经网络研究,但直到2017年Google Brain团队提出Transformer架构后才广泛应用于深度学习。它通过计算序列内部元素间的相关性,捕捉复杂依赖关系,并支持并行化训练,显著提升了处理长文本和序列数据的能力。相比传统的RNN、LSTM和GRU,自注意力机制在自然语言处理(NLP)、计算机视觉、语音识别及推荐系统等领域展现出卓越性能。其核心步骤包括生成查询(Q)、键(K)和值(V)向量,计算缩放点积注意力得分,应用Softmax归一化,以及加权求和生成输出。自注意力机制提高了模型的表达能力,带来了更精准的服务。
|
10天前
|
机器学习/深度学习 算法 PyTorch
深度强化学习中SAC算法:数学原理、网络架构及其PyTorch实现
软演员-评论家算法(Soft Actor-Critic, SAC)是深度强化学习领域的重要进展,基于最大熵框架优化策略,在探索与利用之间实现动态平衡。SAC通过双Q网络设计和自适应温度参数,提升了训练稳定性和样本效率。本文详细解析了SAC的数学原理、网络架构及PyTorch实现,涵盖演员网络的动作采样与对数概率计算、评论家网络的Q值估计及其损失函数,并介绍了完整的SAC智能体实现流程。SAC在连续动作空间中表现出色,具有高样本效率和稳定的训练过程,适合实际应用场景。
47 7
深度强化学习中SAC算法:数学原理、网络架构及其PyTorch实现
|
13天前
|
存储 物联网 大数据
探索阿里云 Flink 物化表:原理、优势与应用场景全解析
阿里云Flink的物化表是流批一体化平台中的关键特性,支持低延迟实时更新、灵活查询性能、无缝流批处理和高容错性。它广泛应用于电商、物联网和金融等领域,助力企业高效处理实时数据,提升业务决策能力。实践案例表明,物化表显著提高了交易欺诈损失率的控制和信贷审批效率,推动企业在数字化转型中取得竞争优势。
60 14
|
21天前
|
网络协议 安全 网络安全
探索网络模型与协议:从OSI到HTTPs的原理解析
OSI七层网络模型和TCP/IP四层模型是理解和设计计算机网络的框架。OSI模型包括物理层、数据链路层、网络层、传输层、会话层、表示层和应用层,而TCP/IP模型则简化为链路层、网络层、传输层和 HTTPS协议基于HTTP并通过TLS/SSL加密数据,确保安全传输。其连接过程涉及TCP三次握手、SSL证书验证、对称密钥交换等步骤,以保障通信的安全性和完整性。数字信封技术使用非对称加密和数字证书确保数据的机密性和身份认证。 浏览器通过Https访问网站的过程包括输入网址、DNS解析、建立TCP连接、发送HTTPS请求、接收响应、验证证书和解析网页内容等步骤,确保用户与服务器之间的安全通信。
84 1
|
2月前
|
SQL Java 数据库连接
Mybatis架构原理和机制,图文详解版,超详细!
MyBatis 是 Java 生态中非常著名的一款 ORM 框架,在一线互联网大厂中应用广泛,Mybatis已经成为了一个必会框架。本文详细解析了MyBatis的架构原理与机制,帮助读者全面提升对MyBatis的理解和应用能力。关注【mikechen的互联网架构】,10年+BAT架构经验倾囊相授。
Mybatis架构原理和机制,图文详解版,超详细!

推荐镜像

更多