jQuery技术内幕(二)

240 阅读5分钟

这是我参与11月更文挑战的第12天,活动详情查看:2021最后一次更文挑战

1, 前言

上一章对jQuery的有一个全局的概念和了解,并简单的介绍了一下jQuery构造函数的7中用法,整体上总结了一下jQuery的总体结构,接下来针对jQuery的原型属性和方法,静态属性和方法以及一些核心的工具方法进行分析学习。

2, 回顾

针对上一章的代码,我们继续深入分析

(function(window, undefined) {
// 构造jQury对象
var jQuery = (function() {
     var jQuery = function(selector, context) {
         return new jQuery.fn.init(selector, context, rootjQuery)
     }
    jQuery.fn = jQuery.prototype = {
        constructor: jQuery,
        init: function(selector, context, rootjQuery){
            // 原型方法和属性
        }
    };
    jQuery.fn.init.prototype = jQuery.fn;
    jQuery.extend = jQuery.fn.extend = function() {};
    jQuery.extend({
        // 静态方法和属性
    })
    return jQuery;
})();

window.jQuery = window.$ = jQuery
})(window)

3, jQuery.fn.init

通过上面的代码可以看出:jQuery.fn.init(selector, context, rootjQuery) 有三个参数,这个方法的作用主要是针对参数进行解析,并执行相应的逻辑,返回一个实例。 源码分析

init: function( selector, context, rootjQuery) {
     var match, elem, ret, dec
}
  • selector参数:可以是任意类型的值,但只有undefined, DOM元素, 字符串,函数, jQuery对象, 普通js对象这几种类型是有效的。

  • context参数:可以不传入,或者传入DOM元素,jQuery对象,普通的JS对象

  • rootjQuery参数:包含了document对象的jQury对象

主要:selector不同的参数类型,函数的处理方式是不同的,可参考下面的截图:

jquer.fn.init.png

4, jQuery.buildFragment

方法jQuery.buildFragment(args, nodes, scripts) 有三个参数,其原理是先创建一个文档片段DocumentFragment, 然后调用方法jQuery.clean(elems,context, fragment, scripts)将HMTL代码转换为DOM元素,并存储在创建的文档片段中。

注意: 此方法支持大量节点插入,相比于单个个的插入节点,使用DocumentFragment一次性插入多个节点,性能提升非常明显。

jQuery.buildFragment = function( arges, nodes, scripts) {

}
源码分析:次方法执行的顺序
1, 如果HTML代码符合缓存条件,则尝试从缓存对象jQuery.fragments中读取缓存的DOM元素
2,创建文档片段DocumentFragment
3, 调用jQuery.clean(elems, context, fragment,scripts)将HTML代码转换为DOM元素,
   并存储在创建的文档片段中
4,如果HMTM代码符合缓存条件,则把转换后的DOM元素放入缓存对象jQuery.fragments
5,最好返回文档片段和缓存状态
   { fragement: fragment, cacheable: cacheable }
  • args 参数:数组,待转换为DOM元素的HTML代码
  • nodes 参数: 数组, 文档对象,jQuery对象或者DOM元素,
  • scripts 参数:数组,用于存放HTML代码中的scritp元素,这个参数会被传递到jQuery.clean()中

截图是此方法的执行总结:

jQuery.buildFragment.png

5, jQuery.clean

方法jQuery.clean(elems, context, fragment, scripts) 负责把HTML代码转换成DOM元素,并提取其中的script元素。该方法先创建一个临时的Div元素,并将其插入一个安全文档片段中,然后把HTML代码赋值给DIV元素的innerHTML属性,浏览器回自动生成DOM元素,最后解析DIV元素的子元素得到转换后的DOM元素。

jQuery.clean(elems, context, fragment, scripts)执行的8个步骤:
1,创建一个临时DIV元素,并插入一个安全文档片段中
2,为HTML代码包裹必要的父标签,然后赋值给临时DIV元素的innerHTML属性,从而将HTML代码转换为DOM元素,之后在层层剥去包裹的父元素,得到转换后的DOM元素
3,移除IE自动插入的空tbody元素,插入IE自动剔除的前导空白符
4,取到转换后的DOM元素集合
5,在IE中修复正复选框和单选框的选中状态
6,合并转换后的DOM元素
7,如果传入了文档片段,则提取所有合法的script元素存入数组,并把其他元素插入文档片段
8,最后返回转换后的DOM元素数组
  • elemes 参数: 数组,包含了转换的HTML代码
  • context 参数: 文档对象
  • fragment 参数: 文档片段,作为存放转换后的DOM元素的占位符
  • scripts 参数: 数组,用于存放转换后的DOM元素中的script元素

下面是该方法的执行总结

jQuery-clean.png

6, jQuery.extend()

方法jQuery.extend()jQuery.fn.enxtend() 用于合并两个或多个对象的属性到第一个对象,他们的语法:

jQuery.extend([deep], target, object1 [, objectN])
jQuery.fn.extend([deep], target, object1 [, objectN])
  • deep 参数:是可选的布尔值,表示是否进行深度合并.
  • target参数:是目标对象
  • object1参数: 是源对象

如果提供了两个或者更多的对象,所有源对象的属性将会合并到目标对象,如果仅提供了一个对象,意味着参数target被忽略,jQuery被当作目标对象。

1, jQuery.extend()jQuery.fn.enxtend() 的执行步骤

(1) 修正参数deep, target,源对象的起始下标

(2) 遍历源对象, 遍历源对象的属性,覆盖目标对象的同名属性

7, 原型属性和方法

jQuery.fn = jQuery.prototype = {
    constructor: jQuery,
    init: function(selector, context, rootjQuery) {
    }
    selector: '',
    jquery: '',
    length: 0,
    size: function() {},
    toArray: function() {},
    get: function(num) {},
    pushStack: function(elems,name, selector) {},
    each: function(callback, args) {},
    ready: function(fn) {},
    eq: function(i) {},
    first: function() {},
    last: function() {},
    slice: function() {},
    map: function(callback) {},
    end: function() {},
    push: push,
    sort: [].sort,
    splice: [].splice
}

原型属性和方法可总结为:jQuery.fn=jQuery.prototype

.constructor指向构造函数
.init(selector, context, rootjQuery)构造函数,解析参数,返回实例
.selector记录jQuery查找和过滤DOM元素的选择器表达式
.jquery正在使用的jQuery版本
.lengthjQuery对象中元素的个数
.size()返回当前jQuery对象中元素的个数
.toArray()将当前jQuery对象转换为真正的数组
.get([index])返回当前对象中指定位置的元素或包含了全部元素的数组
.pushStack(element, name, args)创建一个新的空jQuery对象,然后把DOM元素集合放入这个jQuery对象中,并保留引用
.each(function(index, element))遍历当前jQury对象中的元素,并在每一个元素上执行的数组
.ready(handle)绑定ready事件
.eq(index)将匹配元素集合缩减为位于指定元素的新位置
.first()将匹配元素集合缩减为集合中的第一个元素
.last()将匹配元素集合缩减为集合中的最后一个元素
.map(callback(index, ele))遍历当前jQuery对象中的元素,并在每个元素上执行回调函数,返回一个新的对象
.end()结束当前链条中最近的操作,并将匹配元素集合还原为之前的状态
.push()Array.prototype.push()
.sort()[].sort
.splice()[].plice
.slice()将匹配元素集合缩减为指定范围的子集