Jquery源码中的Javascript基础知识(四)— jQuery.fn.init方法
$() 即调用了jQuery.fn.init方法
jQuery = function( selector, context ) {
return new jQuery.fn.init( selector, context, rootjQuery );
}
下面是init方法代码:
init: function( selector, context, rootjQuery ) {
var match, elem;
if ( !selector ) {
return this;
}
if ( typeof selector === "string" ) {
// code
} else if ( selector.nodeType ) {
this.context = this[0] = selector;
this.length = 1;
return this;
} else if ( jQuery.isFunction( selector ) ) {
return rootjQuery.ready( selector );
}
if ( selector.selector !== undefined ) {
this.selector = selector.selector;
this.context = selector.context;
}
return jQuery.makeArray( selector, this );
}
可以看到,里面对参数 selector 可能出现的值都做了判断处理。
1.是否为错误的值,如:$(""), $(null), $(undefined), $(false)。
2.是否为字符串。
3.是否为节点元素对象。如:$(this), $(document)。
4.是否为函数。如:$(function(){})。
5.是否为jQuery对象。如:$($(element))。
6.是否为数组或json。
当参数是字符串的时候
if ( typeof selector === "string" ) {
if ( selector.charAt(0) === "<" && selector.charAt( selector.length - 1 ) === ">" && selector.length >= 3 ) {
match = [ null, selector, null ];
} else {
match = rquickExpr.exec( selector );
}
// 创建元素或者选择ID
if ( match && (match[1] || !context) ) {
// 创建元素
if ( match[1] ) {
// code
// 选择ID
} else {
// code
}
// 其他选择器
} else if ( !context || context.jquery ) {
return ( context || rootjQuery ).find( selector );
} else {
return this.constructor( context ).find( selector );
}
}
首先给变量match进行赋值
第一种情况
if ( selector.charAt(0) === "<" && selector.charAt( selector.length - 1 ) === ">" && selector.length >= 3 ) {
match = [ null, selector, null ];
}
charAt方法可返回指定位置的字符。符合条件的字符串如:
"<div>", "<div></div>", "<div>111</div>"
第二种情况
match = rquickExpr.exec( selector );
rquickExpr前面已经定义过
rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,
这种语法创建了一个RegExp对象
exec方法找到匹配内容后会返回一个数组,包含表达式的完整匹配以及子表达式的匹配等,否则返回null。符合条件的字符串如:
"<div>111", "#id"
接着看后面的代码:
if ( match && (match[1] || !context) ) {
if ( match[1] ) {
// code 创建元素
} else {
// code 选择ID
}
}
由上面对match的赋值分析可以知道
这里面是针对创建元素和选择id两种情况进行处理,即我们平时这样使用的时候:
$('<div>'), $('#id')
内部又一个if-else语句则分别是对创建元素和选择ID进行处理
下面看处理创建元素部分:
if ( match[1] ) {
context = context instanceof jQuery ? context[0] : context;
jQuery.merge( this, jQuery.parseHTML(
match[1],
context && context.nodeType ? context.ownerDocument || context : document,
true
) );
if ( rsingleTag.test( match[1] ) && jQuery.isPlainObject( context ) ) {
for ( match in context ) {
if ( jQuery.isFunction( this[ match ] ) ) {
this[ match ]( context[ match ] );
} else {
this.attr( match, context[ match ] );
}
}
}
return this;
}
这里简单介绍一下parseHTML方法和merge方法。
jQuery.parseHTML方法的作用是将字符串转换成节点数组,如:

jQuery.merge方法的作用一般是合并数组

在这里也可以合并json

不过json的形式有一定特殊性,需要是类似这样的:
var obj = {
0 : 'a',
1 : 'b',
length : 2
}
在我们平时使用jQuery选取或创建元素后,jQuery对象中都会为节点元素创建出一个类似数组的结构,方便后续的操作。

继续往后看还有一段代码:
if ( rsingleTag.test( match[1] ) && jQuery.isPlainObject( context ) ) {
for ( match in context ) {
if ( jQuery.isFunction( this[ match ] ) ) {
this[ match ]( context[ match ] );
} else {
this.attr( match, context[ match ] );
}
}
}
这段代码的作用是给元素标签添加属性,如:

第一个条件
rsingleTag = /^<(\w+)\s*\/?>(?:<\/\1>|)$/,
test() 方法用于检测一个字符串是否匹配某个模式,有则返回true,无返回false。
符合这个正则的字符串如:
"<div>", "<div></div>",也就是单标签。
第二个条件
jQuery.isPlainObject( context ) 判断第二个参数是否为对象字面量。
接着for...in 语句遍历对象中的属性,如果存在与属性同名的方法,就调用此方法(例如上面例子中调用了html方法),否则就调用attr方法。
创建元素就到这里。接下来就是选择id了
if ( match[1] ) {
// code
} else {
elem = document.getElementById( match[2] );
if ( elem && elem.parentNode ) {
// Inject the element directly into the jQuery object
this.length = 1;
this[0] = elem;
}
this.context = document;
this.selector = selector;
return this;
}
这里就很简单了,直接用getElementById方法获取目标元素,然后就是对应进行赋值,创建之前说过的类似数组的结构。
下面看除了创建元素和选择id之外的情况
if ( match && (match[1] || !context) ) {
// code
} else if ( !context || context.jquery ) {
return ( context || rootjQuery ).find( selector );
} else {
return this.constructor( context ).find( selector );
}
可以看到,不管走后面哪条分支,最终调用的都是find方法,所以,选择类,选择元素和更加复杂的选择器都并没有在init方法中做处理,而是调用了find,这个就到后面再说。
最后我们来看一下参数除了字符串以外其他情况:
if ( typeof selector === "string" ) {
// code
} else if ( selector.nodeType ) {
this.context = this[0] = selector;
this.length = 1;
return this;
} else if ( jQuery.isFunction( selector ) ) {
return rootjQuery.ready( selector );
}
if ( selector.selector !== undefined ) {
this.selector = selector.selector;
this.context = selector.context;
}
return jQuery.makeArray( selector, this );
当参数为元素对象或jQuery对象时,对一些属性进行赋值。
当参数为函数时,调用了ready方法,
所以,$(function(){})这种写法算是文档加载$(document).ready(function(){})的一种简写方式。
makeArray方法类似于之前提到的merge方法,一般可以用来把节点元素转换为数组

也可以转换为json,同样第二参数需要是类数组的形式

好了,总结一下, jQuery.fn.init方法对不同类型的参数进行处理,并且参数为字符串时,内部主要对创建元素和选择id作了处理,其他情况则交给find方法,最终构造出一个关于节点元素的类数组结构以及对一些属性的初始化。
Jquery源码中的Javascript基础知识(四)— jQuery.fn.init方法的更多相关文章
- Jquery源码中的Javascript基础知识(三)
这篇主要说一下在源码中jquery对象是怎样设计实现的,下面是相关代码的简化版本: (function( window, undefined ) { // code 定义变量 jQuery = fun ...
- Jquery源码中的Javascript基础知识(一)
jquery源码中涉及了大量原生js中的知识和概念,文章是我在学习两者的过程中进行的整理和总结,有不对的地方欢迎大家指正. 本文使用的jq版本为2.0.3,附上压缩和未压缩版本地址: http://a ...
- Jquery源码中的Javascript基础知识(二)
接上一篇,jquery源码的这种写法叫做匿名函数自执行 (function( window, undefined ) { // code })( window ); 函数定义了两个参数window和u ...
- jquery源码中noConflict(防止$和jQuery的命名冲突)的实现原理
jquery源码中noConflict(防止$和jQuery的命名冲突)的实现原理 最近在看jquery源码分析的视频教学,希望将视频中学到的知识用博客记录下来,更希望对有同样对jquery源码有困惑 ...
- jQuery源码中的“new jQuery.fn.init()”什么意思?
所有文章搬运自我的个人主页:sheilasun.me 引子 最近打算试试看看jQuery的源码,刚开个头就卡住了.无论如何都理解不了jQuery源码入口部分中的 return new jQuery.f ...
- jQuery源码中的赌博网站
前言 jQuery源码中有赌博网站? 起因是公司发的一份自查文件,某银行在日常安全运营过程中发现在部分jQuery源码中存在赌博和黄色网站链接. 链接分为好几个: www.cactussoft.cn ...
- 关于jQuery源码中(function(window,undefined){//dosomething()})(window)写法解释
一.首先是最常见的闭包 (Closure) 范式自执行函数的写法,这里用匿名函数封装(构造块级作用域),避免了匿名函数内部的代码与外部之间发生冲突(如使用了相同的变量名). (function() { ...
- jQuery源码逐行分析学习02(第一部分:jQuery的一些变量和函数)
第一次尝试使用Office Word,方便程度大大超过网页在线编辑,不过初次使用,一些内容不甚熟悉,望各位大神见谅~ 在上次的文章中,把整个jQuery的结构进行了梳理,得到了整个jQuery的简化结 ...
- jQuery 源码中的 camelCase
先看一下源码 //65-72行 // Matches dashed string for camelizing //匹配连字符 ‘-’ 和其后的第一个字母或数字,如果是字母,则替换为大写,如果是数字, ...
随机推荐
- NumPy的array
1.numpy包中的array数组,用于弥补列表可以存储任意的数据类型的不足,因为有时候我们需要存储某种类型的数据在数组中,这才是数组的本来内涵.我们通过向numpy.array()函数中传递pyth ...
- (转)c语言随机数srandom( )
转自:http://zhidao.baidu.com/question/334364810.html调用随机数函数 rand()() 的时候, 实际得到的这个随机数并不是绝对随机的,它是以一个初始值, ...
- HDU 3255 Farming (线段树+扫面线,求体积并)
题意:在一块地上种蔬菜,每种蔬菜有个价值.对于同一块地蔬菜价值高的一定是最后存活,求最后的蔬菜总值. 思路:将蔬菜的价值看做高度的话,题目就转化成求体积并,这样就容易了. 与HDU 3642 Get ...
- 使用 Struts 2 开发 RESTful 服务
REST 简介 REST 是英文 Representational State Transfer 的缩写,这个术语由 Roy Thomas Fielding 博士在他的论文<Architectu ...
- C#中String跟string的“区别”
string是c#中的类,String是.net Framework的类(在C# IDE中不会显示蓝色) C# string映射为.net Framework的String 如果用string,编译器 ...
- Understanding node.js
Node.js has generally caused two reactions in people I've introduced it to. Basically people either ...
- JavaScript基于对象编程
js面向对象特征介绍 javascript是一种面向(基于)对象的动态脚本语言,是一种基于对象(Object)和事件驱动(EventDirven)并具有安全性能的脚本语言.它具有面向对象语言所特有的各 ...
- div滚动条
给DIV限定宽度或高度,并指定overflow样式为auto,这样当内空超出后就会自动出现滚动条了.如<div style="width:100px; height:100px; ov ...
- java--vo
VO是跟数据库里表的映射,一个表对应一个VO DAO是用VO来访问真实的表,对数据库的操作都在DAO中完成 BO是业务层,做逻辑处理的 VO , PO , BO , QO, DAO ,POJO, O/ ...
- JavaWeb项目开发案例精粹-第4章博客网站系统-001设计
1. 2. 3. # MySQL-Front 5.0 (Build 1.0) /*!40101 SET @OLD_SQL_MODE=@@SQL_MODE */; /*!40101 SET SQL_MO ...