对jQuery.extend()方法的分析
jQuery.extend方法是我们常用的方法,也是jQuery源码中的基础方法。它的主要作用是:将一个或多个“源对象”合并到一个“目标对象”中,并返回目标对象。它主要有三种表现形式:
a、jQuery.extend(destination, source1, source2, source3 ....)
b、jQuery.extend( source )
c、jQuery.extend(boolean, destination, source1, source2, source3 ....)
a方式第一个参数作为“目标对象”,其它参数作为“源对象”。
b方式只有一个参数,这里的这个参数变成了“源对象”,“目标对象”变成了jQuery。说白了就是"源对象"的属性,变成jQuery函数的静态方法或属性。
c方式的第一个参数是boolean类型的,第二个参数是"目标对象",剩下的参数是“源对象”。当第一个参数的值为true时,表示对象合并时支持“深拷贝”。
知道了函数的用法,我们肯定好奇jQuery是怎么实现的,想看看jQuery的源码。不过在看jQuery源码之前,我们不妨试着写写这个方法的功能,然后在回过头来看jQuery源码,感受可能更深,看到的东西可能越多。
我们先不要给自己压力,先从最简单的开始,要实现的方法就两个参数:第一个参数是:“目标对象”,第二个参数是:“源对象”。先实现把“源对象”合并到“目标对象”中。代码如下:
var Test = function(){}
Test.extend0 = function(destination, source){
for(var key in source){
destination[key] = source[key]
}
return destination
}
第二步实现可以传入多个参数,第一个参数是目标对象,其他参数是源对象。代码如下:
Test.extend1 = function(){
var destination = arguments[0]
var sourceArr = Array.prototype.slice.call(arguments,1)
for(var i = 0, len = sourceArr.length; i < len; i++){
var source = sourceArr[i]
for(var key in source){
destination[key] = source[key]
}
}
return destination
}
第三步实现只有一个参数时,将参数对象的属性附加给Test。代码如下:
Test.extend2 = function(){
var argumentsLen = arguments.length
if( argumentsLen === 1 ){
var source = arguments[0]
for(var key in source){
Test[key] = source[key]
}
}else{
var destination = arguments[0]
var sourceArr = Array.prototype.slice.call(arguments,1)
for(var i = 0, len = sourceArr.length; i < len; i++){
var source = sourceArr[i]
for(var key in source){
destination[key] = source[key]
}
}
return destination
}
}
第四步实现“深拷贝”,第一个参数是是否进行深拷贝的布尔判断,第二个参数是目标对象,其他参数是源对象。代码如下:
Test.extend3 = function(){
var argumentsLen = arguments.length
if( argumentsLen === 1 ){
var source = arguments[0]
for(var key in source){
Test[key] = source[key]
}
}else{
var firstItem = arguments[0]
var isBoolean = typeof firstItem === "boolean"
var destination = isBoolean ? arguments[1] : firstItem
var startNum = isBoolean ? 2 : 1
var sourceArr = Array.prototype.slice.call(arguments,startNum)
for(var i = 0, len = sourceArr.length; i < len; i++){
var source = sourceArr[i]
if( isBoolean ){
deepExtend( destination, source )
}else{
for(var key in source){
destination[key] = source[key]
}
}
}
return destination
}
}
function deepExtend(destination, source){
for(var key in source){
var value = source[key]
if( value instanceof Array ){
destination[key] = arguments.callee.call( destination[key] || [], value )
}else if( value instanceof Object ){
destination[key] = arguments.callee.call( destination[key] || {}, value )
}else{
destination[key] = source[key]
}
}
return destination
}
好了,我们按照自己的思路,粗略的实现了自己的extend方法,现在就看下jQuery对extend的实现,对比学习一下。源码如下:
jQuery.extend = jQuery.fn.extend = function() {
var src, copyIsArray, copy, name, options, clone,
target = arguments[0] || {},
i = 1,
length = arguments.length,
deep = false;
// Handle a deep copy situation
if ( typeof target === "boolean" ) {
deep = target;
// skip the boolean and the target
target = arguments[ i ] || {};
i++;
}
// Handle case when target is a string or something (possible in deep copy)
if ( typeof target !== "object" && !jQuery.isFunction(target) ) {
target = {};
}
// extend jQuery 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;
}
}
}
}
// Return the modified object
return target;
}
通过对比,我们发现:
a、jQuery在代码组织和实现上更加优雅。
b、jQuery考虑到了一些特殊情况。比如:
if ( target === copy ) {
continue;
}
这是为了避免无限循环,“源对象”的属性指向的是“目标对象”,当合并对象时,也就是将“自己”复制为“自己的属性”。这是不可取的。
c、jQuery在数组(jQuery.isArray)和“纯粹对象”(jQuery.isPlainObject)的判断上,考虑的更精细。
先自己想思路去实现,再反过来对比学习,这种学习方法感觉挺好的。a、加强了独立思考能力。b、发现新的学习内容。c、暴漏自己的不足。
对jQuery.extend()方法的分析的更多相关文章
- jQuery extend方法使用及实现
一.jQuery extend方法介绍 jQuery的API手册中,extend方法挂载在jQuery和jQuery.fn两个不同对象上方法,但在jQuery内部代码实现的是相同的,只是功能却不太一样 ...
- jQuery 源码解析二:jQuery.fn.extend=jQuery.extend 方法探究
终于动笔开始 jQuery 源码解析第二篇,写文章还真是有难度,要把自已懂的表述清楚,要让别人听懂真的不是一见易事. 在 jQuery 源码解析一:jQuery 类库整体架构设计解析 一文,大致描述了 ...
- jquery.extend方法
jquery.extend()用来扩展jquery中方法,实现插件. 1.jQuery.extend函数详细用法! 扩展jQuery静态方法. 1$.extend({ 2test:function() ...
- jQuery.extend方法和开发中变量的复用
最近在用commonJS规范进行客户端开发,遇到如下问题: 一般一个模块内部可能会定义一系列变量或一系列相关变量,比如写了一个颜色选择弹框模块大概会有如下变量定义 var settings = { / ...
- jQuery extend方法介绍
jQuery为开发插件提拱了两个方法,分别是: jQuery.fn.extend(object); jQuery.extend(object); jQuery.extend(object);为扩展jQ ...
- jQuery extend 方法使用 (转)
方法介绍 jQuery 的 API 手册中,extend 方法挂载在 jQuery 和 jQuery.fn 两个不同的对象上,但在 jQuery 内部代码实现的是相同的,只是功能各不相同. 先看看官方 ...
- jQuery extend方法详解
先说个概念的东西: jQuery为开发插件提拱了两个方法,分别是: $.fn.extend(item):为每一个实例添加一个实例方法item.($("#btn1") 会生成一个 j ...
- 对jQuery.isArray方法的分析
jQuery.isArray方法应于判断是不是数组,是的话返回true,否则返回false.调用如:jQuery.isArray([]),返回true.其实现源码如下: isArray: Array. ...
- jQuery.extend()方法
定义和用法 jQuery.extend()函数用于将一个或多个对象的内容合并到目标对象. 注意: 1. 如果只为$.extend()指定了一个参数,则意味着参数target被省略.此时,target就 ...
随机推荐
- CSS之perspective
<!DOCTYPE html> <html> <head> <style> #div1 { position: relative; height: 15 ...
- 第六十篇、音视频采集硬编码(H264+ACC)
使用 AVCaptureSession进行实时采集音视频(YUV.),编码 通过AVCaptureVideoDataOutputSampleBufferDelegate获取到音视频buffer- 数据 ...
- JavaScript DOM编程艺术第一章:JavaScript简史
本系列的博客是由本人在阅读<JavaScript DOM编程艺术>一书过程中做的总结.前面的偏理论部分都是书中原话,觉得有必要记录下来,方便自己翻阅,也希望能为读到本博客的人提供一些帮助, ...
- FreeMarker-Built-ins for strings
http://freemarker.org/docs/ref_builtins_string.html Page Contents boolean cap_first capitalize chop_ ...
- Linux ed
ed 编辑器是 Linux 操作系统下最简单的文本编辑器.它是以行为单位对文件进行编辑的编辑器,而不像 MS-DOS 系统下的 edit 那样是以整个屏幕框架为单位对文件进行编辑的.因此,如果你已经习 ...
- Linux C 程序 文件属性,文件删除(15)
dup ,dup2,fcntl,ioctl系统调用 . dup ,dup2 函数 int dup(int oldfd) int dup(int oldfd , int newfd) dup用来复制参数 ...
- mvc的删除
有UserInfo一个实体类,db代表请求上下文 属性有ID,UserName,UserPass,Email var users=from c in db.UserInfo select c; var ...
- Winform DataGridView添加列头checkbox
using System; using System.Data; using System.Drawing; using System.Windows.Forms; using Yanwen.Logi ...
- 手写一个自己的简单MVC框架myPHP
myPHP框架 采用的是MVC 思想,应用纯面向对象及项目单一入口,实现的一个自定义的框架.(自己兴趣的练习) 一.项目单一入口 入口文件 myphp\index.php前台 一个网站所有的请求都请求 ...
- nginx禁止访问某个后缀名的文件
猛然发现通过http://ip:端口号/路径/config.ini竟然能下载项目代码的配置文件,检查nginx配置,原来是没有加限制,立即加上,并记录如下: location ~* \.(ini|do ...