$() 即调用了jQuery.fn.init方法

  1. jQuery = function( selector, context ) {
  2. return new jQuery.fn.init( selector, context, rootjQuery );
  3. }

下面是init方法代码:

  1. init: function( selector, context, rootjQuery ) {
  2. var match, elem;
  3. if ( !selector ) {
  4. return this;
  5. }
  6. if ( typeof selector === "string" ) {
  7. // code
  8. } else if ( selector.nodeType ) {
  9. this.context = this[0] = selector;
  10. this.length = 1;
  11. return this;
  12. } else if ( jQuery.isFunction( selector ) ) {
  13. return rootjQuery.ready( selector );
  14. }
  15. if ( selector.selector !== undefined ) {
  16. this.selector = selector.selector;
  17. this.context = selector.context;
  18. }
  19. return jQuery.makeArray( selector, this );
  20. }

可以看到,里面对参数 selector 可能出现的值都做了判断处理。

1.是否为错误的值,如:$(""), $(null), $(undefined), $(false)。

2.是否为字符串。

3.是否为节点元素对象。如:$(this), $(document)。

4.是否为函数。如:$(function(){})。

5.是否为jQuery对象。如:$($(element))。

6.是否为数组或json。

当参数是字符串的时候

  1. if ( typeof selector === "string" ) {
  2. if ( selector.charAt(0) === "<" && selector.charAt( selector.length - 1 ) === ">" && selector.length >= 3 ) {
  3. match = [ null, selector, null ];
  4. } else {
  5. match = rquickExpr.exec( selector );
  6. }
  7.  
  8. // 创建元素或者选择ID
  9. if ( match && (match[1] || !context) ) {
  10.  
  11. // 创建元素
  12. if ( match[1] ) {
  13. // code
  14.  
  15. // 选择ID
  16. } else {
  17. // code
  18. }
  19.  
  20. // 其他选择器
  21. } else if ( !context || context.jquery ) {
  22. return ( context || rootjQuery ).find( selector );
  23. } else {
  24. return this.constructor( context ).find( selector );
  25. }
  26. }

首先给变量match进行赋值

第一种情况

  1. if ( selector.charAt(0) === "<" && selector.charAt( selector.length - 1 ) === ">" && selector.length >= 3 ) {
  2. match = [ null, selector, null ];
  3. }

charAt方法可返回指定位置的字符。符合条件的字符串如:

"<div>",  "<div></div>",  "<div>111</div>"

第二种情况

  1. match = rquickExpr.exec( selector );

rquickExpr前面已经定义过

  1. rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,

这种语法创建了一个RegExp对象

exec方法找到匹配内容后会返回一个数组,包含表达式的完整匹配以及子表达式的匹配等,否则返回null。符合条件的字符串如:

"<div>111",   "#id"

接着看后面的代码:

  1. if ( match && (match[1] || !context) ) {
  2. if ( match[1] ) {
  3. // code 创建元素
  4. } else {
  5. // code 选择ID
  6. }
  7. }

由上面对match的赋值分析可以知道

这里面是针对创建元素和选择id两种情况进行处理,即我们平时这样使用的时候:

$('<div>'), $('#id')

内部又一个if-else语句则分别是对创建元素和选择ID进行处理

下面看处理创建元素部分:

  1. if ( match[1] ) {
  2. context = context instanceof jQuery ? context[0] : context;
  3.  
  4. jQuery.merge( this, jQuery.parseHTML(
  5. match[1],
  6. context && context.nodeType ? context.ownerDocument || context : document,
  7. true
  8. ) );
  9.  
  10. if ( rsingleTag.test( match[1] ) && jQuery.isPlainObject( context ) ) {
  11. for ( match in context ) {
  12. if ( jQuery.isFunction( this[ match ] ) ) {
  13. this[ match ]( context[ match ] );
  14. } else {
  15. this.attr( match, context[ match ] );
  16. }
  17. }
  18. }
  19.  
  20. return this;
  21. }

这里简单介绍一下parseHTML方法和merge方法。

jQuery.parseHTML方法的作用是将字符串转换成节点数组,如:

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

在这里也可以合并json

不过json的形式有一定特殊性,需要是类似这样的:

  1. var obj = {
  2. 0 : 'a',
  3. 1 : 'b',
  4. length : 2
  5. }

在我们平时使用jQuery选取或创建元素后,jQuery对象中都会为节点元素创建出一个类似数组的结构,方便后续的操作。

继续往后看还有一段代码:

  1. if ( rsingleTag.test( match[1] ) && jQuery.isPlainObject( context ) ) {
  2. for ( match in context ) {
  3. if ( jQuery.isFunction( this[ match ] ) ) {
  4. this[ match ]( context[ match ] );
  5. } else {
  6. this.attr( match, context[ match ] );
  7. }
  8. }
  9. }

这段代码的作用是给元素标签添加属性,如:

第一个条件

  1. rsingleTag = /^<(\w+)\s*\/?>(?:<\/\1>|)$/,

test() 方法用于检测一个字符串是否匹配某个模式,有则返回true,无返回false。

符合这个正则的字符串如:

"<div>", "<div></div>",也就是单标签。

第二个条件

jQuery.isPlainObject( context ) 判断第二个参数是否为对象字面量。

接着for...in 语句遍历对象中的属性,如果存在与属性同名的方法,就调用此方法(例如上面例子中调用了html方法),否则就调用attr方法。

创建元素就到这里。接下来就是选择id了

  1. if ( match[1] ) {
  2. // code
  3. } else {
  4. elem = document.getElementById( match[2] );
  5. if ( elem && elem.parentNode ) {
  6. // Inject the element directly into the jQuery object
  7. this.length = 1;
  8. this[0] = elem;
  9. }
  10. this.context = document;
  11. this.selector = selector;
  12. return this;
  13. }

这里就很简单了,直接用getElementById方法获取目标元素,然后就是对应进行赋值,创建之前说过的类似数组的结构。

下面看除了创建元素和选择id之外的情况

  1. if ( match && (match[1] || !context) ) {
  2. // code
  3. } else if ( !context || context.jquery ) {
  4. return ( context || rootjQuery ).find( selector );
  5. } else {
  6. return this.constructor( context ).find( selector );
  7. }

可以看到,不管走后面哪条分支,最终调用的都是find方法,所以,选择类,选择元素和更加复杂的选择器都并没有在init方法中做处理,而是调用了find,这个就到后面再说。

最后我们来看一下参数除了字符串以外其他情况:

  1. if ( typeof selector === "string" ) {
  2. // code
  3. } else if ( selector.nodeType ) {
  4. this.context = this[0] = selector;
  5. this.length = 1;
  6. return this;
  7. } else if ( jQuery.isFunction( selector ) ) {
  8. return rootjQuery.ready( selector );
  9. }
  10.  
  11. if ( selector.selector !== undefined ) {
  12. this.selector = selector.selector;
  13. this.context = selector.context;
  14. }
  15.  
  16. return jQuery.makeArray( selector, this );

当参数为元素对象或jQuery对象时,对一些属性进行赋值。

当参数为函数时,调用了ready方法,

所以,$(function(){})这种写法算是文档加载$(document).ready(function(){})的一种简写方式。

makeArray方法类似于之前提到的merge方法,一般可以用来把节点元素转换为数组

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

好了,总结一下, jQuery.fn.init方法对不同类型的参数进行处理,并且参数为字符串时,内部主要对创建元素和选择id作了处理,其他情况则交给find方法,最终构造出一个关于节点元素的类数组结构以及对一些属性的初始化。

Jquery源码中的Javascript基础知识(四)— jQuery.fn.init方法的更多相关文章

  1. Jquery源码中的Javascript基础知识(三)

    这篇主要说一下在源码中jquery对象是怎样设计实现的,下面是相关代码的简化版本: (function( window, undefined ) { // code 定义变量 jQuery = fun ...

  2. Jquery源码中的Javascript基础知识(一)

    jquery源码中涉及了大量原生js中的知识和概念,文章是我在学习两者的过程中进行的整理和总结,有不对的地方欢迎大家指正. 本文使用的jq版本为2.0.3,附上压缩和未压缩版本地址: http://a ...

  3. Jquery源码中的Javascript基础知识(二)

    接上一篇,jquery源码的这种写法叫做匿名函数自执行 (function( window, undefined ) { // code })( window ); 函数定义了两个参数window和u ...

  4. jquery源码中noConflict(防止$和jQuery的命名冲突)的实现原理

    jquery源码中noConflict(防止$和jQuery的命名冲突)的实现原理 最近在看jquery源码分析的视频教学,希望将视频中学到的知识用博客记录下来,更希望对有同样对jquery源码有困惑 ...

  5. jQuery源码中的“new jQuery.fn.init()”什么意思?

    所有文章搬运自我的个人主页:sheilasun.me 引子 最近打算试试看看jQuery的源码,刚开个头就卡住了.无论如何都理解不了jQuery源码入口部分中的 return new jQuery.f ...

  6. jQuery源码中的赌博网站

    前言 jQuery源码中有赌博网站? 起因是公司发的一份自查文件,某银行在日常安全运营过程中发现在部分jQuery源码中存在赌博和黄色网站链接. 链接分为好几个: www.cactussoft.cn ...

  7. 关于jQuery源码中(function(window,undefined){//dosomething()})(window)写法解释

    一.首先是最常见的闭包 (Closure) 范式自执行函数的写法,这里用匿名函数封装(构造块级作用域),避免了匿名函数内部的代码与外部之间发生冲突(如使用了相同的变量名). (function() { ...

  8. jQuery源码逐行分析学习02(第一部分:jQuery的一些变量和函数)

    第一次尝试使用Office Word,方便程度大大超过网页在线编辑,不过初次使用,一些内容不甚熟悉,望各位大神见谅~ 在上次的文章中,把整个jQuery的结构进行了梳理,得到了整个jQuery的简化结 ...

  9. jQuery 源码中的 camelCase

    先看一下源码 //65-72行 // Matches dashed string for camelizing //匹配连字符 ‘-’ 和其后的第一个字母或数字,如果是字母,则替换为大写,如果是数字, ...

随机推荐

  1. Sqli-labs less 45

    Less-45 同样的,45关与43关的payload是一样的,只不过45关依旧没有报错信息. 登录 username:admin Password:c');create table less45 l ...

  2. Javascript实现 图片的无缝滚动

    <!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <m ...

  3. Razor视图引擎 语法学习(一)

    ASP.NET MVC是一种构建web应用程序的框架,它将一般的MVC(Model-View-Controller)模式应用于ASP.NET框架: ASP.NET约定优于配置:基本分为模型(对实体数据 ...

  4. Codeforces Round #259 (Div. 2) C - Little Pony and Expected Maximum (数学期望)

    题目链接 题意 : 一个m面的骰子,掷n次,问得到最大值的期望. 思路 : 数学期望,离散时的公式是E(X) = X1*p(X1) + X2*p(X2) + …… + Xn*p(Xn) p(xi)的是 ...

  5. ListView中EditText的数据加载错乱的问题

    我在ListView中用BaseAdapter的getView()方法加载适配器,每个Item里有一个TextView和一个EditText,当我在第一个EditText里面输入数据,比如1234时, ...

  6. Linux网络编程9——对TCP与UDP的简易封装2.0

    具体生成动态库的操作及使用该动态库的操作请参见上篇博文.以下仅仅列出改进版本的代码. 代码 my_socket.h #ifndef __MY_SOCKET_H__ #define __MY_SOCKE ...

  7. C/C++ 位域知识小结

    C/C++ 位域知识小结 几篇较全面的位域相关的文章: http://www.uplook.cn/blog/9/93362/ C/C++位域(Bit-fields)之我见 C中的位域与大小端问题 内存 ...

  8. 如何使用SPY++查找

    自动化测试中,如果需要做UI automation的时候往往需要抓取object的工具.实际上这种工具有很多,认识的大牛使用SPY++,于是我也选择了这个.下面列出基本使用方法.有点像XACC spy ...

  9. Mita和Maui

    参考:http://blog.csdn.net/popeer/article/details/6002541 UI自动化的框架,MS内部使用的不对外开放的框架.UI Automation 离不开像Mi ...

  10. Delphi对象变成Windows控件的前世今生(关键是设置句柄和回调函数)goodx

    ----------------------------------------------------------------------第一步,准备工作:预定义一个全局Win控件变量,以及一个精简 ...