jQuery深入之源码解析(三)——构造jQuery对象

jQuery构造对象函数有:

  1. jQuery([selector,[context]])
  2. jQuery(element)
  3. jQuery(elementArray)
  4. jQuery(object)
  5. jQuery(jQuery object)
  6. jQuery(html,[ownerDocument])
  7. jQuery(html,[attributes])
  8. jQuery()
  9. jQuery(callback)
function(window,undefined){
var jQuery=(function(){
    var jQuery = function( selector, context ) {
        return new jQuery.fn.init( selector, context );
        //这里用new,省去了构造函数jQuery()前面的运算符new,因此我们可以直接写jQuery()
    },
    //一堆局部变量声明
    rtrim = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,
    rmsPrefix = /^-ms-/,
    rdashAlpha = /-([\da-z])/gi,
    fcamelCase = function( all, letter ) {
        return letter.toUpperCase();
    };
    //覆盖构造函数jQuery的原型对象
    jQuery.fn = jQuery.prototype ={
    .....//一堆原型属性和原型方法
    };
    jQuery.extend = jQuery.fn.extend = function(){
    ....//
    };
    //jQuery.extend()和jQuery.fn.extend(),用于合并两个或多个对象的属性到第一个对象
    jQuery.extend({
    //一堆静态属性和方法
    });
    return jQuery;
    })();
    //其他模块代码
    window.jQuery=window.$=jQuery;
    })(window);

为什么要覆盖jQuery()的原型对象jQuery.prototype

因为在原型对象jQuery.prototype上定义的属性和方法会被所有jQuery对象继承,可以有效的减少每个jQuery对象所需的内存。

为什么要在构造函数jQuery()内部用运算符new创建并返回另一个构造函数实例

这里写图片描述
用new的原因是因为,我们每次创建一个对象或者实例的时候,都是在运算符后面跟一个new运算符
例如:

var mydate=new Date()

如果构造函数有返回值,运算符new创建的对象会被丢弃,返回值将作为new表达式的值。
jQuery通过在构造函数jQuery()内部用运算符new创建并返回另一个构造函数实例,省去了构造函数jQuery()前面的new,因此我们在创建jQuery对象时可以省略运算符new 直接写jQuery()
后面的

window.jQuery=window.$=jQuery;

也是为了更简写,因此我们在创建jQuery对象时可以写$()=jQuery()=window.jQuery
这里写图片描述
这里写图片描述

jQuery.fn.init()

init = jQuery.fn.init = function( selector, context, root ) {
        var match, elem;

        //参数selector可以转换为false,如果是"" ,null,undefined,false ,返回this(空的jQuery,length=0if ( !selector ) {
            return this;
        }
        ....
        }

一个普通的jQuery对象 $(“body”)
可以看到jQuery.fn.init[1]
length=1
这里写图片描述
一个空的jQuery对象
并且它什么都没有,没有context ,selector,只有原型prototype可以查看原型,它的length=0

这里写图片描述
处理nodeType,文本中有3个p
因此是jQuery.fn.init[3]
这里写图片描述

//如果参数selector是字符串
if ( typeof selector === "string" ) {
            if ( selector[ 0 ] === "<" &&
                selector[ selector.length - 1 ] === ">" &&
                selector.length >= 3 ) {

                // Assume that strings that start and end with <> are HTML and skip the regex check
                match = [ null, selector, null ];

            } else {
                match = rquickExpr.exec( selector );
            }
                   // 处理 $(#id)
                    {
                    elem = document.getElementById( match[ 2 ] );
                    //检查parentNode,因为Blackberry会返回已经不在文档中的Dom节点
                    if ( elem && elem.parentNode ) {
            //从这里就能看到为id元素构造了length 以及手动设置第一个元素this[0]=elem
                        this.length = 1;
                        this[ 0 ] = elem;
                    }
                    //并返回了jQuery对象
                    this.context = document;
                    this.selector = selector;
                    return this;
                }
    // Easily-parseable/retrievable ID or TAG or CLASS selectors
    //2.2.4版本
    // Prioritize #id over <tag> to avoid XSS via location.hash (#9521)
    // Strict HTML recognition (#11290: must start with <)
    //严格控制了HTML必须以<开头,不识别"ab<div>"
    rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/
    //1.7.3版本  #是为了防止XSS攻击
    quickExpr=/^(?:[^#<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/

说明一下正则表达式
1、2.2.4版本不匹配”ab < d i v >”这样的字符串了,对于“#”也就直接到#id中去识别了,因此省略了 [^#<] (不匹配#和<的字符串,如“abc”)
2、另外说一下(?:pattern),第一次遇到这种表达式(因为平时很少接触正则),这句话的作用是:匹配 pattern 但不获取匹配结果,也就是说这是一个非获取匹配,不进行存储供以后使用。这在使用 “或” 字符 (|) 来组合一个模式的各个部分是很有用。例如, ‘industr(?:y|ies) 就是一个比 ‘industry|industries’ 更简略的表达式。
正则语句 rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/的测试:
这里写图片描述
所谓XSS攻击:
只参照《jQuery技术内幕》中的介绍,在应用代码中出现$(location.hash),会根据location.hash的值来执行不同的逻辑。用户可以自行在浏览器地址中修改hash值为”#”,并重新打开这个页面,如果没有#(在jQuery1.6.3之前的版本),”#”会被认为是HTML代码并创建img元素,因为src不存在,oneror事件被触发,从而弹出窗口1。这样攻击者就可以在句柄onerror事件编写恶意代码,例如,读取用户cookie,发起Ajax请求。



本文是在阅读《jQuery技术内幕》后写的,以及慕课网上的jQuery源码解析,也结合了网上的其他对jQuery的分析。
另外我阅读的jQuery源码的version 是 v2.2.4
阅读好的源码有利于对好的代码风格进行学习,由于水平有限,这些都是我的学习心得体会。

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值