jQuery技术

第二章 jQuery技术解密 (三)

字号+ 作者:H5之家 来源:H5之家 2017-11-11 11:32 我要评论( )

2.3 破解 jQuery 选择器接口jQuery 选择器功能强大,但是用法简单,它仅仅提供了一个接口:jQuery(),也可以简写为 $() 。用法如此简单,但又具有如此强大的处理

2.3 破解 jQuery 选择器接口

jQuery 选择器功能强大,但是用法简单,它仅仅提供了一个接口:jQuery(),也可以简写为 $() 。用法如此简单,但又具有如此强大的处理能力,使 jQuery 必然成为众人追捧的对象。

在上一节中,我们重点分析了 jQuery 框架的雏形,而对于选择器并没有深入分析,仅仅提供了一个简单的 DOM 元素选择作为演示,目的是方便读者理解该框架的架设思路和过程。本节将重点研究 jQuery 选择器的设计思路、实现过程和工作原理。

2.3.1 简单但很复杂的黑洞

前面说到,jQuery 提供了惟一的接口 (jQuery() 或者 $()) 使选择器与外界进行交流。那么这个对象是如何生成的呢?

jQuery 框架的基础是查询,即查询文档元素对象,因此我们可以认为 jQuery 对象就是一个选择器,并在此基础上构建和运行查询过滤器。

jQuery 查询的结果是获取 DOM 元素,这些查询到的 DOM 元素又是如何存储的呢?

根据前面的介绍,我们初步了解到它把查询的结果存储到 jQuery 对象内。由于查询的结果可能是单个元素,也可能是集合,因此,jQuery 对象内应该定义了一个集合。这个集合专门负责存放查询到的 DOM 元素。这正如 JavaScript 中的 Function 对象一样,其内部也构建了一个集合对象 Arguments ,专门负责存储函数的参数。

但是,Functiono 对象和 Arguments 是两个相互独立的概念,仅通过 arguments 属性联系在一起。也就是说 Arguments 对象并非是 Function 对象的子对象,或者是它的内部组成部分。而 jQuery 对象与查询结果的数据集合就不同了,它是完全作为 jQuery 对象的一部分而存在的。

另外,jQuery 虽然仅提供了一个入口,但是它的构建并不只局限于从 DOM 文档树中查询到 DOM 元素,DOM 元素也有可能从别的集合中转移过来的,或者是从 HTML 片断生成的等。

例如,类似下面的代码在 jQuery 应用中经常会看到。

$("div.red").css("display", "none");       // 将 class 为 red 的 div 元素隐藏显示

var width = $("div .red").width();            // 获取 div 元素下 class 为 red 的元素的宽度

var html = $(document.getElementById("wrap")).html();       // 获取 id 为 wrap 元素的 innerHTML 值

$("#wrap", document.forms[0]).css("color", "red"); // 将在第一个 form 元素下 id 为 wrap 元素的字体颜色设置为红色

$("<div>hello,world</div>").appendTo("#wrap");   // 将 HTML 字符串信息追加到 id 为 wrap 元素的末尾

在 $() 函数中可以包含选择字符串、HTML 字符串、 DOM 对象和数据集合等不同类型的参数。jQuery 是如何分辨这些参数是选择符字符串、HTML字符串、DOM对象或数据集合的呢?

为了方便读者理解这其中的奥妙,我们不妨把 jQuery 框架进行简化,先删除所有方法、函数以及逻辑代码,然后在 init() 构造器中,使用 alert() 方法获取 selector 参数的类型和信息,其代码如下。

<script type="text/javascript"> (function(){ var window = this; jQuery = window.jQuery = window.$ = function(selector, context){ return new jQuery.fn.init(selector, context); }; jQuery.fn = jQuery.prototype = { init: function(selector, context){ alert(selector); } }; })(); window.onload = function(){ $("div.red"); // 获取 "div.red" $("div .red"); // 获取 "div .red" $(document.getElementById("wrap")); // 获取 "[object]" $("#wrap", document.forms[0]); // 获取 "#wrap" $("<div>hello,world</div>"); // 获取 "<div>hello,world</div>" }; </script> <div id="wrap"></div> 2.3.2 盘根错节的逻辑关系

根据 jQuery 官网提供的 API 文档可知, jQuery() 提供了以下 4 种构建 jQuery 对象的方式。

其中 jQuery 可以使用 $ 简写。上述四种构建 jQuery 对象的方式是经常用到的。从上述参数列表可以看出,其实 jQuery 的参数可以是任意元素。例如:

$("div > p");// 参数可以是字符串

$( $("div >p") );// 参数可以是 jQuery 对象或者类数组 (ArrayLike) 的集合

$(document);// 参数可以是 DOM 元素

$();// $(document) 简写

$(function(){});// $(document).ready() 的简写

$([]);// 参数可以是数组

$({});// 参数可以是对象

$(1);// 参数可以是数字,即把 1 存储在 jQuery 对象的数据集合中

虽然说,在上面的示例中最后 4 行代码都可以被解析,但是这些参数数据是被存储到 ArrayLike (类数组) 集合中的,而不是被转换为 DOM 元素。虽然语法不错,解析正常,但是它们无法完成实际应用,所以不建议传入非 DOM 元素的参数。

注意:jQuery 对象的方法都是针对 DOM 元素对象进行的操作,如果不清楚其使用的话,很有可能会导致错误。

下面我们就顺着 jQuery 框架的这个惟一入口,慢慢向里爬进,以窥视其中的秘密。

***** 当我们调用 jQuery() 方法时,它没有被实例化,也就是说 jQuery 类型被抛弃了,我们仅仅把它作为一个普通函数来调用,此时该方法中的 this 关键字指向的是 Window 对象,而不是 jQuery 对象,请读者务必注意。 ******

不过,当调用该方法时,会返回一个 jQuery.fn.init 类型的实例,同时,jQuery 又使用自己的原型对象覆盖了 jQuery.fn.init 类型的原型对象,所以就形成了一种错觉,很多初学者往往在这里栽了跟头。下面是 jQuery 框架中的核心代码 (节选) 。

jQuery = window.jQuery = window.$ = function(selector, context){

return new jQuery.fn.init(selector, context);

};

jQuery.fn.init.prototype = jQuery.fn;

jQuery 对象不是通过 new jQuery 来继承其 prototype 中的方法的,而是通过 jQuery.fn.init 初始化构造器生成的。所以,为 jQuery.prototype 添加函数集也就失去了存在价值。虽然直接使用 new jQuery() 也是允许的,但是由于该函数的返回值覆盖了 new jQuery() 创建的实例对象,所以使用 new jQuery() 来构建 jQuery 对象也是无法存活的。 (---???----)

 

1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,请转载时务必注明文章作者和来源,不尊重原创的行为我们将追究责任;3.作者投稿可能会经我们编辑修改或补充。

相关文章
  • jquery常用技术总结

    jquery常用技术总结

    2017-11-11 11:33

  • 每日学习心得:$.extend()方法和(function($){...})(jQuery)详解

    每日学习心得:$.extend()方法和(function($){...})(jQuery)详解

    2017-11-10 18:05

  • jQuery的豆瓣API插件 jQuery Douban

    jQuery的豆瓣API插件 jQuery Douban

    2017-11-10 18:00

  • jQuery基础学习遍历 closest()方法

    jQuery基础学习遍历 closest()方法

    2017-11-09 14:01

网友点评
c