jQuery的无new创建方法

一般我们去写一个框架,会采用什么样的设计呢?比如设计一个jQuery框架,一般我们会创建一个函数对象

function jQuery(params){
  //构造函数
}jQuery.prototype.init = function(params){  //初始化操作}
jQuery.prototype.html = function(html){
  //实现类似设置innerHTML的操作
}
var jq = new jQuery("#id");
jq.init();
jq.html("test");

我想这是我们最常见的使用方式,这种方式需要new一个新的实例,然后再进行初始化操作,然后才能继续操作,很显然这样会比较繁琐而且代码较多,而jQuery中的使用方法却非常简洁:

获取指定元素:$("#id")/$(".class")/$("body").html("test");

创建html片段$("<div></div>").html("test");

设置文档加载完成后的方法$(function(){XXX});

等等,为何jQuery的使用方法如此简单,这是因为jQuery设计的是一种无new的创建方法,这是jQuery独特的设计思路之一。

我们打开jQuery初始化的这块代码,发现基本结构是这样子的(提取主要框架部分源码):

(function( window, undefined ) {

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

    jQuery.fn = jQuery.prototype = {

        constructor: jQuery,
        init: function( selector, context, rootjQuery ) {

if ( !selector ) {
                     return this;
                 }

if ( typeof selector === "string" ) {
                    if ( match && (match[1] || !context) ) {
                        return this;
                    } else if ( !context || context.jquery ) {
                        return ( context || rootjQuery ).find( selector );
                    } else {
                        return this.constructor( context ).find( selector );
                    }
                } else if ( selector.nodeType ) {
                     return this;

} else if ( jQuery.isFunction( selector ) ) {
                     return rootjQuery.ready( selector );
                }

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

return jQuery.makeArray( selector, this );

        },     html:function(value){      //实现类似innerHTML操作     }
    }

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

})( window );

1. 首先把代码封装在一个匿名函数里面,防止污染全局环境,然后创建一个对象jQuery,这个对象接受两个参数selector,context,其中selector就是我们通常传入的 #id,.class等字符串,这个对象函数里面并没有做什么逻辑而是直接返回了一个原型上的init方法,然后把参数传了进去。

2. init方法接受了3个参数,然后在内部进行了各种判断,根据不同的场景,返回一个不同的实例对象,类似一个工厂方法。

3. 将jQuery.fn.init的原型挂载到jquery的原型上。

4. 将jQuery的constructor还原为jQuery

init方法的内部逻辑我们后面再看,首先看下为何jQuery要这样做?

首先jQuery在构造函数里面就执行了new方法并执行了init方法,将new和init两步直接合并成一步,而且自带new操作,不需要用户再去进行new的操作,但是为何要使用一个原型上的init方法,而不是在自身自己new出一个对象呢?

想象一下如果jQuery这样写

 var jQuery = function( selector, context ) {     //做上面的各种场景判断
        return new jQuery( selector, context, rootjQuery );
 }

这样写会存在一个问题,jQuery函数内部new一个新的jQuery,然后会一直这样new下去无限循环,陷入死循环。为了防止这种情况的出行,jQuery将这部分逻辑放在了原型中的一个init方法,由init方法来进行工厂方法的处理,return new jQuery.fn.init( selector, context, rootjQuery ),这样就避免了死循环的问题,而且实现了一步到位的初始化。

但是这样写还存在一个问题,init方法里面的return this是指向的jQuery的实例对象,那他将无法访问jQuery的原型对象,比如说jQuery.prototype.html方法,因为html的方法是jQuery.prototype上的所以init方法无法访问这个函数,为了解决这个问题,我们看到之前的源码有最后一行:

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

其中jQuery.fn就是jQuery.prototpye,也就等价于

jQuery.prototpye.init.prototype = jQuery.prototpye;

这句话的意思是,把init的方法的原型改为指向jQuery的原型,这样new init的出来的实例对象也就等价于new jQuery的实例对象,所以也就可以访问jQuery的原型方法了。

jQuery.prototype.init和jQuery的原型指向的是同一个对象,这样不管是init还是jQuery去修改原型对象都是等价的,这样就实现了上面提到的问题。

最后,jQuery再把constructor还愿回来到jQuery,防止构造函数指向错误,引起调用问题,为何要这样处理呢?因为我们是把jQuery的prototype直接覆盖成了一个新的实例对象,所以jQuerty的constructor就变成了{}的构造函数Object,所以需要将constructor还原为真正的jQuery。

对比下两种原型改写方式:

//方式1jQuery.prototype.html = function(value){}
//方式2
jQuery.prototype = {
           html:function(value){}
}

两种方式看起来好像没啥区别,但其实区别很大,第一种是给jQuery的prototype新增一个方法,这种方式是不会影响jQuery的constructor,还是function jQuery(),

而第二种方式是直接覆盖了jQuery的prototype,这种情况下的constructor会被直接改写为{html:function(value)}这个实例对象的构造函数,也就是function Object()

所以需要重置一下jQuery的constructor

时间: 2024-08-10 21:15:01

jQuery的无new创建方法的相关文章

jQuery实现form表单基于ajax无刷新提交方法详解

本文实例讲述了jQuery实现form表单基于ajax无刷新提交方法.分享给大家供大家参考,具体如下: 首先,新建Login.html页面: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.o

jquery源码学习笔记(一)jQuery的无new构建

本人是一名.net程序员..... 你一个.net coder 看什么jQuery 源码啊? 原因吗,很简单.技多不压身吗(麻蛋,前端工作好高...羡慕). 我一直都很喜欢JavaScript,废话不多说了,直接切入正题. 最近看了好几篇jQuery 源码的文章,对于jQuery的无new构建  很是不解. 查了很多资料,总算是搞明白了. jQuery的无new构建 jQuery框架的核心就是从HTML文档中匹配元素并对其执行操作. 回想一下使用 jQuery 的时候,实例化一个 jQuery

jQuery教程 - Ajax之load()方法

jQuery教程 - Ajax之load()方法 标签: jqueryajaxxmlhttprequesthtmlcallback 2009-10-05 14:54 3700人阅读 评论(3) 收藏 举报  分类: jQuery(7)  版权声明:本文为博主原创文章,未经博主允许不得转载. jQuery对Ajax操作进行了封装,在jQuery中$.ajax()方法属于最底层的方法,第2层是laod().$.get()和$.post()方法,第3层是$.getScript()和$.getJSON(

jquery中html 与 text方法的区别

jquery中html 与 text方法的区别 24 May 2012/in 网站设计和开发 /by Bruce 接鉵jquery的时间并不长,以前都是用直接用js写的,现在发现在jquery这个框架用起来很方便,不但代码量少了,使用也比较简单,对于浏览器的兼容问题也不用担心,在使用的过程中也会遇到一些疑问,在html标签中附加子标签时所用的方法html()与text()的区别. 通常在用jquery写ajax时,都会用到html()这个方法,而不用text()这个方法,他们之间有什么区别呢?

利用 jQuery UI 和 Ajax 创建可定制的 Web 界面

如今,网站比以往更具可定制性,允许用户更改其空间,根据自己的喜好对其进行个性化.个性化的主页或仪表板页面(例如 iGoogle.MyYahoo! 和 MyAOL)日渐普及,大多数 Web 应用程序内甚至也整合了类似的功能.jQuery 库简化了此类复杂 JavaScript 交互的编写,随着 jQuery UI 的引入,这项功能得到了进一步的简化,该库以易于访问的 jQuery 插件的形式提供了常用用户界面类型. 本文介绍了如何利用 Ajax 和 jQuery UI 创建具有各种定制功能的高度可

手机和PC站点击商务通无轨迹解决方法

手机站点击商务通无轨迹解决方法 手机站点击商务通咨询按钮是很多时候会出现后台无法统计到访客的浏览轨迹的情况,这种情况是因为部分手机浏览器打开新的页面不传递来路页面地址信息所导致的.下面为大家介绍一种能解决这一情况的方法: 代码如下 <script type="text/javascript"> function online(){ //商务通轨迹 var e = 'wap'; if(arguments.length == 1){ e = arguments[0]; } if

Java基础---Java中无参数无返回值方法使用(三十六)

Java 中无参无返回值方法的使用 如果方法不包含参数,且没有返回值,我们称为无参无返回值的方法. 方法的使用分两步: 第一步,定义方法 例如:下面代码定义了一个方法名为 show ,没有参数,且没有返回值的方法,执行的操作为输出 " welcome to imooc. " 注意哦: 1. 方法体放在一对大括号中,实现特定的操作 2. 方法名主要在调用这个方法时使用,需要注意命名的规范,一般采用第一个单词首字母小写,其它单词首字母大写的形式 第二步,调用方法 当需要调用方法执行某个操作

jquery ajax无刷新删除

职位列表里面显示应聘的简历: 点击简历的数量,弹出层(用load方法调用加载) 弹出的层里面删除简历(无刷新删除),实现方法 ? 1 2 3 4 5 6 7 8 9 10 11 12 $(".Del a").click(function () {             var mid = $(this).attr("name");               var jobid = $(this).attr("lang"); //职位id   

Asp.net中JQuery、ajax调用后台方法总结

通过上一篇文章实例的实现,整个过程当中学习到很多知识点,了解了Jquery.Ajax在asp.net中的运用,加以总结,其实原理都是一样的,理解了一种,其他的注意很少的区别就可以了.灵活运用: 1.有参数的方法调用 示例代码如下:前台jQuery代码:$(function() {  知道的一种就是ajax调后台的方法. 1.有参数的方法调用 示例代码如下: 前台jQuery代码: [plain] view plaincopyprint? <span style="font-size:18p