jQuery源码分析3--jQ原型1

jQuery1.8.1的95~289行,关于jQuery的prototype上构造函数init方法的介绍。

一、prototype的赋值与覆盖

首先是给jQuery的原型重新覆盖了对象:

jQuery.fn = jQuery.prototype = {//.......}

而在覆盖的对象中有个constructor属性。需要这样赋值的原因是此处我们是直接覆盖了原型对象,而不是修改他的属性,constructor会在创建时,指向jQuery,因为被覆盖了,所以需要重新指向。比如:

var Fun = function() { // Fun构造函数
    this.place = 'earth';
};

Fun.prototype.show = function() { // 添加属性,属于赋值操作
    console.log(this.place);
};

var fn = new Fun();
console.log(fn.constructor === Fun); // true

Fun.prototype = { // 覆盖了原先的prototype
    show: function() {
        console.log(this.place);
    }
};

var fn1 = new Fun();
console.log(fn1.constructor === Fun); // false,因为是{}覆盖的,所以指向Object

正是这种原因,这儿对constructor进行了重新的赋值。

二、init函数

该init函数是我们每次使用$(jQuery)时,创建jQuery对象的构造函数。

init: function( selector,context,rootjQuery ) {

init函数带有三个参数,第一个是选择器,可以是id、class或复杂的字符串,也可以是dom对象等。第二个参数是上下文,正常情况下都是document,有些时候,当我们在iframe中使用时,需要对这个context进行赋值。第三个参数是document的jQ对象,在906行:rootjQuery = jQuery(document)。

空值过滤

进入函数内部,首先是过滤了空字符串(””)、null、undefined、false这些值,直接返回this。

dom转化jqdom

紧接着的if用于处理dom,我们都知道,$(dom)这样使用时,我们可以得到这个dom的jQ对象。于是,这儿给new出的实例添加了个0的属性,且值是该dom。并将length置为1。注:这儿的对象是类数组,他的属性值类似于数组的下标,且含有length,但他实质上不是数组,就和函数内部的arguments类似。

过滤了以上的条件后,开始处理字符串。我们想想,平时,我们可以写$(‘#box’)、$(‘.class’)、$(‘#box div’)、$(‘<div></div>’)、$(‘<div>111</div>’)、$(function(){})等。这些方式可以细分为创建元素和查找元素。

处理字符串

if ( selector.charAt(0) === "<" && selector.charAt( selector.length - 1 ) === ">" && selector.length >= 3 ) {

该方式查找前后都是标签的html字符串,像$(‘<div></div>’)、$(‘<div>111</div>’)这些,而$(‘<div>123’)这种是不会进入if的。if中得到了这样的一个match数组:

match = [ null,selector,null ];

而else中,利用正则的匹配也得到了一个长度是三的类似的数组,

match = rquickExpr.exec( selector );
rquickExpr = /^(?:[^#<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/,59行,用来检测html的字符串形式的。正则匹配用到的知识就不展开了

正则匹配完成之后,会对匹配结果进行判断,

if ( match && (match[1] || !context) ) {

当存在match时,且match中第二个元素是true或是false但context上下文不存在时才会走。所以进入该if的有:$(‘<div></div>’)、$(‘<div>111</div>’)、$(‘<div>123’),$(‘#box’)要是能进入if的话,创建时的上下文必须不给赋值。这样一判断之后,是创建元素还是查找元素,大致已经被区分开了。

创建元素

随后使用 if ( match[1] ) { 来区分掉刚才上下文为false的id查找字符串。因此,能够进入if的都是创建元素的字符串。接下来,首先是对context的赋值,保证该context是原生的dom对象,并且对doc变量进行赋值。随后调用jQ的工具方法parseHTML将匹配到的HTML字符串转化为jq对象。如何转化的,到parseHTML定义的地方在叙述。

注:$(‘<div>123’)得到的元素不会带123,是因为正则匹配的时候,match第二个值是<div>,所以创建的时候,只是创建了div元素,并没有赋值。

 if ( rsingleTag.test( match[1] ) && jQuery.isPlainObject( context ) ) {
     this.attr.call( selector,true );
 }

检测当时单个元素时,且context是一个纯对象时,就系那个context下的属性给到创建的那个元素上。这也就是当我们写$(‘<p></p>’,{‘title’: ‘aaa’,html: ‘abcd’}).appendTo(‘html’)这种方式时,会给新创建的p元素添加两个属性。

再来看下进入else中的$(‘#box’),使用了元素查找的方式,并且也做了浏览器兼容的处理,查找完成之后,便返回了this。

创建元素解决了,下面是查询元素。

元素查找

else if ( !context || context.jquery ) {

当没有上下文时,直接在document的jQ对象下调用find方法。当context存在时,能够进入的条件就是context下含有jQuery属性,比如$(‘.class’,$(‘div#box’))这样的写法就会进入该条件下。

而$(‘.class’,document.getElementById(‘box’))这种的会进入下一个else,执行find操作。

$(function)

当传入function的方式还没有考虑到,当使用$(function() {})时,会调用jQ根对象下的ready方法,也就是文档加载完成后执行。这也就是为什么我们常常说,$(function(){})是$(document).ready(function(){})的一种简写方式。

最后剩下个if判断传入的selector的selector属性:

 if ( selector.selector !== undefined ) {
     this.selector = selector.selector;
     this.context = selector.context;
 }

该方式是兼容$(jQ对象)这种方式的,这样也增加了$的容错性。

将所有的情况都考虑一遍,整个init函数就是这种情况:

init: function( selector,rootjQuery ) {
    if ( !selector ) {
        // $(""),$(null),$(undefined),$(false)
    }
    if ( selector.nodeType ) {
        // $(DOMElement)
    }
    if ( typeof selector === "string" ) {
        // $('<div>123'),$('<div>123</div>'),$('432<div>123</div>243'),$('#box'),$('#box',document)
        // $('<div></div>',{title: '123'}),$(document)),$('.class'),$('#box p')
        if ( match && (match[1] || !context) ) {
            // $('<div>123'),$('<div></div>',{title: '123'})
            if ( match[1] ) {
                // $('<div>123'),$('432<div>123</div>243')
                if ( rsingleTag.test( match[1] ) && jQuery.isPlainObject( context ) ) {
                    // $('<div></div>',{title: '123'})
                }
            } else {
                // $('#box')
            }
        } else if ( !context || context.jquery ) {
            // $('#box',$('#box p')
        } else {
            // $('#box',document)
        }
    } else if ( jQuery.isFunction( selector ) ) {
        // $(function)
    }
    if ( selector.selector !== undefined ) {
       // $(jQobject)
    }
}

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


问题背景 最近小伙伴提了一个希望提高后台下拉列表可操作性的需求,原因是下拉列表选项过多,每次下拉选择比较费时费力且容易出错,硬着头皮啃了啃前端知识,网上搜寻了一些下拉列表实现的资料,这里总结一下。 P
// n位随机数生成 function randomNum(n) { let sString = &quot;&quot;; let strings = &quot;abcdefghijklmnopq
HTML是HyperText Markup Language的简称,中文名称:超文本标记语言,它是一种用于创建网页的 标准标记语言
层叠样式表(英文全称:Cascading Style Sheets)是一种用来表现HTML或XML(标准通用标记语言的一个子集)等文件样式的计算机语言。
JavaScript 是脚本语言,是一种解释性脚本语言(代码不进行预编译)
本文由葡萄城技术团队原创并首发 转载请注明出处:葡萄城官网,葡萄城为开发者提供专业的开发工具、解决方案和服务,赋能开发者。 一名开发者或设计师通常可以在一秒内指出优秀的设计,但对于糟糕的设计只需最多半
本文由葡萄城技术团队原创并首发 转载请注明出处:葡萄城官网,葡萄城为开发者提供专业的开发工具、解决方案和服务,赋能开发者。 Excel是我们办公中常用的工具 ,它几乎能为我们处理大部分数据,友好的交互
转载请注明出处:葡萄城官网,葡萄城为开发者提供专业的开发工具、解决方案和服务,赋能开发者。 原文出处:https://blog.bitsrc.io/8-tips-for-an-awesome-sign
本文由葡萄城技术团队于博客园翻译并首发 转载请注明出处:葡萄城官网,葡萄城为开发者提供专业的开发工具、解决方案和服务,赋能开发者。 如果我们自己编写从URL中分析和提取元素的代码,那么有可能会比较痛苦
转载请注明出处:葡萄城官网,葡萄城为开发者提供专业的开发工具、解决方案和服务,赋能开发者。 原文出处:https://blog.bitsrc.io/what-is-deno-and-will-it-r
转载请注明出处:葡萄城官网,葡萄城为开发者提供专业的开发工具、解决方案和服务,赋能开发者。 原文出处:https://blog.bitsrc.io/4-reasons-to-use-sass-in-y
转载请注明出处:葡萄城官网,葡萄城为开发者提供专业的开发工具、解决方案和服务,赋能开发者。 原文出处:https://blog.bitsrc.io/vuejs-3-0-0-beta-features-
转载请注明出处:葡萄城官网,葡萄城为开发者提供专业的开发工具、解决方案和服务,赋能开发者。 原文出处:https://blog.bitsrc.io/sessionstorage-and-localst
一直以来,JavaScript使用数组和对象来定义和存放结构化数据, 在这篇文章中,我们将一起深挖另一种对象Map的一切,我们将会去了解它是什么、如何遍历、都包括什么属性和方法以及优缺点是什么。
由于CSS的出现,现在的网站风格已经与它们很早之前的样子有了很大的不同。CSS的出现为原本平平无奇的网页注入了活力。这也是网站的用户体验得到进一步进化的原因。这可能就是当今几乎所有的网站或多或少都在使
自苹果推出了iPhone应用商店以来,App成为了我们生活中不可或缺的一部分,而对于实体业务也是如此,现在各行业都在推出自己的App,但有没有人想过这样一种场景,如果自己的潜在客户还没有安装你的App
转载请注明出处:葡萄城官网,葡萄城为开发者提供专业的开发工具、解决方案和服务,赋能开发者。 原文出处:https://blog.bitsrc.io/10-top-chrome-extensions-f
转载请注明出处:葡萄城官网,葡萄城为开发者提供专业的开发工具、解决方案和服务,赋能开发者。 原文出处:https://blog.bitsrc.io/do-your-buttons-lead-or-mi
本文由葡萄城技术团队原创并首发 转载请注明出处:葡萄城官网,葡萄城为开发者提供专业的开发工具、解决方案和服务,赋能开发者。 前段时间在开发【葡萄城社区】公众号时有一个功能是需要用网页授权认证地址生成二
本文由葡萄城技术团队原创并首发 转载请注明出处:葡萄城官网,葡萄城为开发者提供专业的开发工具、解决方案和服务,赋能开发者。 HTML5的发展改变了互联网技术趋势,前端热度依旧不减,所以对于应用开发人员