- 浏览: 521103 次
- 性别:
- 来自: 北京
博客专栏
-
jQuery技术内幕
浏览量:200763
最新评论
-
青春依旧:
学习html5哪里好?当然华清远见是首选!
[原创] jQuery源码分析-01总体架构 -
追梦1819:
[size=x-small][color=red][/colo ...
[原创] jQuery源码分析-04 选择器-Sizzle-设计思路 -
niuqiang2008:
学习学习
[原创] jQuery源码分析-04 选择器-Sizzle-工作原理 -
liuweihug:
jquery 解析正则表达式及常见的Regex规则和表达式 - ...
[原创] jQuery源码分析-02正则表达式-RegExp-常用正则表达式 -
liang8768:
mark!!!
[原创] jQuery源码分析-00前言开光
作者:nuysoft/高云 QQ:47214707 EMail:nuysoft@gmail.com
毕竟是边读边写,不对的地方请告诉我,多多交流共同进步。本章还未写完,完了会提交PDF。
前记:
想系统的好好写写,但是会先从感兴趣的部分开始。
近期有读者把PDF传到了百度文库上,首先感谢转载和传播,但是据为已有并设置了挺高的财富值才能下载就不好了,以后我整理好了会传到文库上。请体谅一下。
3. 构造jQuery对象
3.1 源码结构
先看看总体结构,再做分解:
(function( window, undefined ) {
var jQuery = (function() { // 构建jQuery对象 var jQuery = function( selector, context ) { return new jQuery.fn.init( selector, context, rootjQuery ); }
// jQuery对象原型 jQuery.fn = jQuery.prototype = { constructor: jQuery, init: function( selector, context, rootjQuery ) { // selector有以下7种分支情况: // DOM元素 // body(优化) // 字符串:HTML标签、HTML字符串、#id、选择器表达式 // 函数(作为ready回调函数) // 最后返回伪数组 } };
// Give the init function the jQuery prototype for later instantiation jQuery.fn.init.prototype = jQuery.fn;
// 合并内容到第一个参数中,后续大部分功能都通过该函数扩展 // 通过jQuery.fn.extend扩展的函数,大部分都会调用通过jQuery.extend扩展的同名函数 jQuery.extend = jQuery.fn.extend = function() {};
// 在jQuery上扩展静态方法 jQuery.extend({ // ready bindReady // isPlainObject isEmptyObject // parseJSON parseXML // globalEval // each makeArray inArray merge grep map // proxy // access // uaMatch // sub // browser });
// 到这里,jQuery对象构造完成,后边的代码都是对jQuery或jQuery对象的扩展 return jQuery;
})();
window.jQuery = window.$ = jQuery; })(window); |
l jQuery对象不是通过 new jQuery 创建的,而是通过 new jQuery.fn.init 创建的
var jQuery = function( selector, context ) { return new jQuery.fn.init( selector, context, rootjQuery ); } |
n jQuery对象就是jQuery.fn.init对象
n 如果执行new jQeury(),生成的jQuery对象会被抛弃,最后返回 jQuery.fn.init对象;因此可以直接调用jQuery( selector, context ),没有必要使用new关键字
l 先执行 jQuery.fn = jQuery.prototype,再执行 jQuery.fn.init.prototype = jQuery.fn,合并后的代码如下:
jQuery.fn.init.prototype = jQuery.fn = jQuery.prototype |
所有挂载到jQuery.fn的方法,相当于挂载到了jQuery.prototype,即挂载到了jQuery 函数上(一开始的 jQuery = function( selector, context ) ),但是最后都相当于挂载到了 jQuery.fn.init.prototype,即相当于挂载到了一开始的jQuery 函数返回的对象上,即挂载到了我们最终使用的jQuery对象上。
这个过程非常的绕,金玉其外“败絮”其中啊!
3.2 jQuery.fn.init
jQuery.fn.init的功能是对传进来的selector参数进行分析,进行各种不同的处理,然后生成jQuery对象。
处理方式 |
|
DOM元素 |
包装成jQuery对象,直接返回 |
body(优化) |
从document.body读取 |
单独的HTML标签 |
document.createElement |
HTML字符串 |
document.createDocumentFragment |
#id |
document.getElementById |
选择器表达式 |
$(…).find |
函数 |
注册到dom ready的回调函数 |
3.3 jQuery.extend = jQuery.fn.extend
// 合并两个或更多对象的属性到第一个对象中,jQuery后续的大部分功能都通过该函数扩展 // 通过jQuery.fn.extend扩展的函数,大部分都会调用通过jQuery.extend扩展的同名函数
// 如果传入两个或多个对象,所有对象的属性会被添加到第一个对象target
// 如果只传入一个对象,则将对象的属性添加到jQuery对象中。 // 用这种方式,我们可以为jQuery命名空间增加新的方法。可以用于编写jQuery插件。 // 如果不想改变传入的对象,可以传入一个空对象:$.extend({}, object1, object2); // 默认合并操作是不迭代的,即便target的某个属性是对象或属性,也会被完全覆盖而不是合并 // 第一个参数是true,则会迭代合并 // 从object原型继承的属性会被拷贝 // undefined值不会被拷贝 // 因为性能原因,JavaScript自带类型的属性不会合并
// jQuery.extend( target, [ object1 ], [ objectN ] ) // jQuery.extend( [ deep ], target, object1, [ objectN ] ) jQuery.extend = jQuery.fn.extend = function() { var options, name, src, copy, copyIsArray, clone, target = arguments[0] || {}, i = 1, length = arguments.length, deep = false;
// Handle a deep copy situation // 如果第一个参数是boolean型,可能是深度拷贝 if ( typeof target === "boolean" ) { deep = target; target = arguments[1] || {}; // skip the boolean and the target // 跳过boolean和target,从第3个开始 i = 2; }
// Handle case when target is a string or something (possible in deep copy) // target不是对象也不是函数,则强制设置为空对象 if ( typeof target !== "object" && !jQuery.isFunction(target) ) { target = {}; }
// extend jQuery itself if only one argument is passed // 如果只传入一个参数,则认为是对jQuery扩展 if ( length === i ) { 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)) ) ) { // 如果copy是数组 if ( copyIsArray ) { copyIsArray = false; // clone为src的修正值 clone = src && jQuery.isArray(src) ? src : []; // 如果copy的是对象 } else { // clone为src的修正值 clone = src && jQuery.isPlainObject(src) ? src : {}; }
// Never move original objects, clone them // 递归调用jQuery.extend 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; }; |
未完待续
评论
jQuery.fn.init.prototype = jQuery.fn = jQuery.prototype
这个并不绕啊,将jQuery.fn.init的prototype属性设置为jQuery.fn,那么使用new jQuery.fn.init()生成的对象的原型对象就是jQuery.fn,
所以挂载到jQuery.fn上面的函数就相当于挂载到jQuery.fn.init()生成的jQuery对象上。
jQuery.fn.init.prototype = jQuery.fn = jQuery.prototype 对于这句话, 前面的jQuery.fn.init.prototype = jQuery.fn这个赋值很好理解,刚开始我没有弄懂为什么jQuery.fn = jQuery.prototype,貌似没什么必要,是,在 var x = jQuery(yyy);这种情况下,确实是没什么必要, 但是如果是这样写 var x = new jQuery();这种写法,就是必须的了
总之: jQuery.fn.init.prototype = jQuery.fn 是应付 var x = jQuery(yyy);这种写法的jQuery.fn = jQuery.prototype 是应付var x = new jQuery(yyy);这种写法的。
你好,请问为什么 jQuery.fn.init.prototype = jQuery.fn 是应付 var x = jQuery(yyy)???
主要是对 对象的维护 因为只要一旦new 就会去查找实例的静态属性方法和对象的prototype属性,将其copy生成一个新的对象,如果中途修改或增加原型对象的属性,那么也会同时更新这个Object对象,原型对象的属性是被其所有的实例所共享的,所以在修改其属性值的同时也需要额外小心,因为一不小心会影响其它的实例对象,所以对象的prototype在这边的重要性不言而喻 jQuery.fn === jQuery.prototype === jQuery.fn.init.prototype ,最后, jQuery返回的对象的成员和 jQuery.fn 的成员匹配。
不清楚为什么要jquery.prototype.
最终生成的jquery对象原型都是init.prototype吧
没那么复杂, 我想原因很简单 jquery.fn比jquery.prototype短,prototype这玩意不能优化, jquery插件都要引用jquery.fn的,我想这是jquery.fn的作用。至于jquery.fn.init.prototype是为了保护jquery, 比如某个笨蛋刚接触jquery直接用jquery.prototype扩展jquery(这是直觉上最容易想到的方法,js嘛),还是这种错误写法jquery.prototype={...} ,如果没有init.prototype, jquery就不能用了。如果这个笨蛋还写了jquery.fn.init.prototype={...},好吧,这个笨蛋很变态,我给他跪了
不清楚为什么要jquery.prototype.
最终生成的jquery对象原型都是init.prototype吧
jQuery.fn.init.prototype = jQuery.fn = jQuery.prototype
这个并不绕啊,将jQuery.fn.init的prototype属性设置为jQuery.fn,那么使用new jQuery.fn.init()生成的对象的原型对象就是jQuery.fn,
所以挂载到jQuery.fn上面的函数就相当于挂载到jQuery.fn.init()生成的jQuery对象上。
jQuery.fn.init.prototype = jQuery.fn = jQuery.prototype 对于这句话, 前面的jQuery.fn.init.prototype = jQuery.fn这个赋值很好理解,刚开始我没有弄懂为什么jQuery.fn = jQuery.prototype,貌似没什么必要,是,在 var x = jQuery(yyy);这种情况下,确实是没什么必要, 但是如果是这样写 var x = new jQuery();这种写法,就是必须的了
总之: jQuery.fn.init.prototype = jQuery.fn 是应付 var x = jQuery(yyy);这种写法的jQuery.fn = jQuery.prototype 是应付var x = new jQuery(yyy);这种写法的。
你好,请问为什么 jQuery.fn.init.prototype = jQuery.fn 是应付 var x = jQuery(yyy)???
主要是对 对象的维护 因为只要一旦new 就会去查找实例的静态属性方法和对象的prototype属性,将其copy生成一个新的对象,如果中途修改或增加原型对象的属性,那么也会同时更新这个Object对象,原型对象的属性是被其所有的实例所共享的,所以在修改其属性值的同时也需要额外小心,因为一不小心会影响其它的实例对象,所以对象的prototype在这边的重要性不言而喻 jQuery.fn === jQuery.prototype === jQuery.fn.init.prototype ,最后, jQuery返回的对象的成员和 jQuery.fn 的成员匹配。
jQuery.fn.init.prototype = jQuery.fn = jQuery.prototype
这个并不绕啊,将jQuery.fn.init的prototype属性设置为jQuery.fn,那么使用new jQuery.fn.init()生成的对象的原型对象就是jQuery.fn,
所以挂载到jQuery.fn上面的函数就相当于挂载到jQuery.fn.init()生成的jQuery对象上。
jQuery.fn.init.prototype = jQuery.fn = jQuery.prototype 对于这句话, 前面的jQuery.fn.init.prototype = jQuery.fn这个赋值很好理解,刚开始我没有弄懂为什么jQuery.fn = jQuery.prototype,貌似没什么必要,是,在 var x = jQuery(yyy);这种情况下,确实是没什么必要, 但是如果是这样写 var x = new jQuery();这种写法,就是必须的了
总之: jQuery.fn.init.prototype = jQuery.fn 是应付 var x = jQuery(yyy);这种写法的jQuery.fn = jQuery.prototype 是应付var x = new jQuery(yyy);这种写法的。
你好,请问为什么 jQuery.fn.init.prototype = jQuery.fn 是应付 var x = jQuery(yyy)???
这句话是不是有问题哈,如果执行new jquery(),返回的还是jquery对象吧,而不是jquery,fn.init对象,平时我们用jquery()或$()返回的是jquery.fn.init对象。
执行new jquery(),js会创建一个jquery类型的对象jqueryTemp,然后调用jquery()方法,把jquery的执行环境设置为先创建的object,类似于调用jquery.call(jqueryTemp),最后返回jqueryTemp。这是通过new jquery()创建对象时,js底层的执行机制吧,其他的通过new创建对象也是一样的。
构造函数如果有返回值,并且返回值是一个对象,则会丢弃运算符 new 创建的临时对象。这个与 jQuery 无关,属于运算符 new 的知识。
同意!
明白了。谢谢!还是对js基础知识掌握的不牢。在学习中!非常感谢!!!
看了lz的回复又重新温故了一下js的基础知识对于以下经典的例子就容易理解了。
例子代码贴出来:
//例子1
var name = "The Window";
var object = {
name : "My Object",
getNameFunc : function(){
return function(){
return this.name;
};
}
};
alert(object.getNameFunc()());
//例子2
var name = "The Window";
var object = {
name : "My Object",
getNameFunc : function(){
var that = this;
return function(){
return that.name;
};
}
};
alert(object.getNameFunc()());
谢谢lz。
明白了。谢谢!还是对js基础知识掌握的不牢。在学习中!非常感谢!!!
jQuery.extend = jQuery.fn.extend = function() {
var options, name, src, copy, copyIsArray, clone,
target = arguments[0] || {},
i = 1,
length = arguments.length,
deep = false;
// Handle a deep copy situation
// 如果第一个参数是boolean型,可能是深度拷贝
if ( typeof target === "boolean" ) {
deep = target;
target = arguments[1] || {};
// skip the boolean and the target
// 跳过boolean和target,从第3个开始
i = 2;
}
// Handle case when target is a string or something (possible in deep copy)
// target不是对象也不是函数,则强制设置为空对象
if ( typeof target !== "object" && !jQuery.isFunction(target) ) {
target = {};
}
// extend jQuery itself if only one argument is passed
// 如果只传入一个参数,则认为是对jQuery扩展
if ( length === i ) {
target = this;
--i;
}
//…………此处省去 大部分代码
本人对上述代码红色字体中 target = this; this具体指代那个对象,此处叫迷惑。希望lz能在百忙之中帮助解答。谢谢
这句话是不是有问题哈,如果执行new jquery(),返回的还是jquery对象吧,而不是jquery,fn.init对象,平时我们用jquery()或$()返回的是jquery.fn.init对象。
执行new jquery(),js会创建一个jquery类型的对象jqueryTemp,然后调用jquery()方法,把jquery的执行环境设置为先创建的object,类似于调用jquery.call(jqueryTemp),最后返回jqueryTemp。这是通过new jquery()创建对象时,js底层的执行机制吧,其他的通过new创建对象也是一样的。
构造函数如果有返回值,并且返回值是一个对象,则会丢弃运算符 new 创建的临时对象。这个与 jQuery 无关,属于运算符 new 的知识。
这句话是不是有问题哈,如果执行new jquery(),返回的还是jquery对象吧,而不是jquery,fn.init对象,平时我们用jquery()或$()返回的是jquery.fn.init对象。
执行new jquery(),js会创建一个jquery类型的对象jqueryTemp,然后调用jquery()方法,把jquery的执行环境设置为先创建的object,类似于调用jquery.call(jqueryTemp),最后返回jqueryTemp。这是通过new jquery()创建对象时,js底层的执行机制吧,其他的通过new创建对象也是一样的。
你看看这句就明白了 jQuery.fn.init.prototype = jQuery.fn = jQuery.prototype
有上面这句 那么 new jQuery.fn.init() === new jQuery()了 只不过
jQuery() 是返回的 new jQuery.fn.init(); 而 var o = new jQuery(); 这2者是相当的了
这句话是不是有问题哈,如果执行new jquery(),返回的还是jquery对象吧,而不是jquery,fn.init对象,平时我们用jquery()或$()返回的是jquery.fn.init对象。
执行new jquery(),js会创建一个jquery类型的对象jqueryTemp,然后调用jquery()方法,把jquery的执行环境设置为先创建的object,类似于调用jquery.call(jqueryTemp),最后返回jqueryTemp。这是通过new jquery()创建对象时,js底层的执行机制吧,其他的通过new创建对象也是一样的。
jQuery.fn.init.prototype = jQuery.fn = jQuery.prototype
这个并不绕啊,将jQuery.fn.init的prototype属性设置为jQuery.fn,那么使用new jQuery.fn.init()生成的对象的原型对象就是jQuery.fn,
所以挂载到jQuery.fn上面的函数就相当于挂载到jQuery.fn.init()生成的jQuery对象上。
jQuery.fn.init.prototype = jQuery.fn = jQuery.prototype 对于这句话, 前面的jQuery.fn.init.prototype = jQuery.fn这个赋值很好理解,刚开始我没有弄懂为什么jQuery.fn = jQuery.prototype,貌似没什么必要,是,在 var x = jQuery(yyy);这种情况下,确实是没什么必要, 但是如果是这样写 var x = new jQuery();这种写法,就是必须的了
总之: jQuery.fn.init.prototype = jQuery.fn 是应付 var x = jQuery(yyy);这种写法的jQuery.fn = jQuery.prototype 是应付var x = new jQuery(yyy);这种写法的。
jQuery.fn.init.prototype = jQuery.fn = jQuery.prototype
这个并不绕啊,将jQuery.fn.init的prototype属性设置为jQuery.fn,那么使用new jQuery.fn.init()生成的对象的原型对象就是jQuery.fn,
所以挂载到jQuery.fn上面的函数就相当于挂载到jQuery.fn.init()生成的jQuery对象上。
再读感觉也不饶,而是惊叹于如此写法的精妙与必要。
jQuery.fn.init.prototype = jQuery.fn = jQuery.prototype
这个并不绕啊,将jQuery.fn.init的prototype属性设置为jQuery.fn,那么使用new jQuery.fn.init()生成的对象的原型对象就是jQuery.fn,
所以挂载到jQuery.fn上面的函数就相当于挂载到jQuery.fn.init()生成的jQuery对象上。
发表评论
-
[原创] jQuery源码分析-04 选择器-Sizzle-设计思路
2011-11-14 20:59 6851作者:nuysoft/高云 QQ:47214707 Em ... -
[原创] jQuery源码分析-04 选择器-Sizzle-工作原理
2011-11-13 23:45 7886作者:nuysoft/高云 QQ:47214707 EM ... -
[原创] jQuery源码分析-02正则表达式-RegExp-常用正则表达式
2011-10-27 01:29 46640作者:nuysoft/JS攻城师/ ... -
[原创] jQuery源码分析-jQuery中的循环技巧
2011-10-27 00:36 14547作者:nuysoft/JS攻城师/高云 QQ:47214707 ... -
[原创] jQuery源码分析-10事件处理-Event-DOM-ready
2011-10-20 01:20 10601作者:nuysoft/JS攻城师/ ... -
[原创] jQuery源码分析-Java工程师应该向jQuery学习的8点建议
2011-10-18 23:56 12249作者:nuysoft/高云 QQ:47214707 EM ... -
[原创] jQuery源码分析-10事件处理-Event-事件绑定与删除-bind/unbind+live/die+delegat/undelegate
2011-10-18 22:31 15668作者:nuysoft/高云 QQ:47214707 EM ... -
[原创] jQuery源码分析-10事件处理-Event-源码结构
2011-10-17 01:01 12119作者:nuysoft/高云 QQ:47214707 EMail ... -
[原创] jQuery源码分析-07数据缓存-Cache
2011-10-13 19:55 12134作者:nuysoft/高云 QQ:47214707 EMail ... -
[原创] jQuery源码分析-06浏览器测试-Support
2011-10-13 19:19 9907作者:nuysoft/高云 QQ:47214707 EMail ... -
[原创] jQuery源码分析系列目录(持续更新)
2011-10-12 12:30 29359作者:nuysoft/高云 QQ:47214707 E ... -
[原创] jQuery源码分析-10事件处理-Event-概述和基础知识
2011-10-12 00:16 12010作者:nuysoft/高云 Q ... -
[原创] jQuery源码分析-08队列 Queue
2011-10-10 23:48 10792作者:nuysoft/高云 Q ... -
[原创] jQuery源码分析-03构造jQuery对象-工具函数
2011-09-29 23:21 29782作者:nuysoft/高云 QQ:47214707 E ... -
[原创] jQuery源码分析-15AJAX-类型转换器
2011-09-29 02:25 7409作者:nuysoft/高云 QQ:47214707 EM ... -
[原创] jQuery源码分析-如何做jQuery源码分析
2011-09-27 00:22 15000近期在ITEYE陆续写了几篇jQuery源码分析,乐在其 ... -
[原创] jQuery源码分析-17尺寸和大小 Dimensions & Offset
2011-09-25 22:05 7050边读边写,不正确的地方,还请各位告诉我,多多交流共同学习, ... -
[原创] jQuery源码分析-15AJAX-前置过滤器和请求分发器
2011-09-23 00:09 13283边读边写,不正确的 ... -
[原创] jQuery源码分析-00前言开光
2011-09-21 23:42 47003jQuery源码分析 - 前言 jQuery凭借简洁的语法和 ... -
[原创] jQuery源码分析-01总体架构
2011-09-21 23:31 751361. 总体架构 1.1 自调用匿名函 ...
相关推荐
### jQuery源码分析—构造jQuery对象 #### 一、源码结构概览 根据所提供的文件内容,本节将深入分析如何构建jQuery对象及其核心构造逻辑。首先,让我们从整体上理解jQuery构造函数的设计思路。 ##### 总体结构 ...
在本部分中,将深入剖析jQuery对象的构造过程,以及其源码结构和核心函数的详细分析。 ### 3. 构造jQuery对象 #### 3.1 源码结构 在分析jQuery对象构造之前,先来看一下总体的源码结构。jQuery的源码是通过一个...
本文将从核心概念、设计模式、主要功能模块等方面进行详尽的jQuery源码分析。 1. **核心概念** - **选择器引擎Sizzle**:jQuery的核心是其高效的选择器引擎Sizzle,它基于CSS选择器实现,能够快速准确地定位DOM...
- **源码结构和核心函数**:详细介绍jQuery对象的创建过程,包括`$`或`jQuery`函数的内部实现,以及如何利用这些核心函数来构建和操作DOM元素。 - **工具函数**:剖析jQuery中用于辅助开发的核心工具函数,如选择器...
### jQuery源码分析-02正则表达式 #### 正则表达式基础与应用 正则表达式是一种用于描述字符模式的强大工具,在多种编程语言中都有应用,其中包括JavaScript。在jQuery这样的JavaScript库中,正则表达式被广泛应用...
《jQuery源码分析——魔术方法》 jQuery,作为一款广泛使用的JavaScript库,以其简洁的API和强大的功能赢得了开发者们的喜爱。在深入理解jQuery的工作原理时,我们常常会遇到一些“魔术方法”,这些方法在特定场景...
《jQuery源码解读——深入理解jQuery v1.10.2》 jQuery,这个轻量级的JavaScript库,自2006年发布以来,以其简洁的API和强大的功能深受开发者喜爱,成为Web开发领域中不可或缺的一部分。本文将对jQuery v1.10.2的...
jQuery源码分析 ...03 构造jQuery对象-源码结构和核心函数 03 构造jQuery对象-工具函数 05 异步队列 Deferred 08 队列 Queue 09 属性操作 10 事件处理-Event-概述和基础知识 15 AJAX-前置过滤器和请求分发器
#### 三、构造jQuery对象 - 源码结构和核心函数 1. **源码结构**:jQuery的核心是一个函数,该函数接受一个文档对象模型(DOM)作为参数,并返回一个包含所有匹配元素的集合。这个函数被称为`jQuery`或`$`。 ```...
在jQuery源码中,构造函数`jQuery()`或简写`$()`接收一个参数,可以是字符串(选择器)、DOM元素、HTML字符串或已存在的jQuery对象。它首先会进行类型检查,然后执行相应的操作。 三、Sizzle选择器引擎 Sizzle是...
通过分析`datagrid`函数,我们可以看到它如何初始化表格,如何处理数据源,以及如何响应用户交互,例如点击列头进行排序。同时,源码中还包含了各种插件,如行选择、编辑功能等,这些都是通过扩展jQuery对象实现的。...