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。
对比下两种原型改写方式:
//方式1
jQuery.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
jQuery的无new创建方法的更多相关文章
- jQuery实现form表单基于ajax无刷新提交方法详解
		本文实例讲述了jQuery实现form表单基于ajax无刷新提交方法.分享给大家供大家参考,具体如下: 首先,新建Login.html页面: <!DOCTYPE html PUBLIC &quo ... 
- 读艾伦的jQuery的无new构建,疑惑分析——jquery源码学习一
		背景: 有心学习jquery源码,苦于自己水平有限,若自己研究,耗时耗力,且读懂之日无期. 所以,网上寻找高手的源码分析.再经过自己思考,整理,验证.以求有所收获. 此篇为读高手艾伦<jQuer ... 
- jquery源码学习笔记(一)jQuery的无new构建
		本人是一名.net程序员..... 你一个.net coder 看什么jQuery 源码啊? 原因吗,很简单.技多不压身吗(麻蛋,前端工作好高...羡慕). 我一直都很喜欢JavaScript,废话不 ... 
- Jquery如何序列化form表单数据为JSON对象  C# ADO.NET中设置Like模糊查询的参数  从客户端出现小于等于公式符号引发检测到有潜在危险的Request.Form 值  jquery调用iframe里面的方法  Js根据Ip地址自动判断是哪个城市 【我们一起写框架】MVVM的WPF框架(三)—数据控件  设计模式之简单工厂模式(C#语言描述)
		jquery提供的serialize方法能够实现. $("#searchForm").serialize();但是,观察输出的信息,发现serialize()方法做的是将表单中的数 ... 
- 实例详解jQuery的无new构建
		jQuery的无new构建 jQuery框架的核心就是从HTML文档中匹配元素并对其执行操作. 回想一下使用 jQuery 的时候,实例化一个 jQuery 对象的方法: // 无 new 构造 $( ... 
- 慕课网-Java入门第一季-7-2 Java 中无参无返回值方法的使用
		来源:http://www.imooc.com/code/1578 如果方法不包含参数,且没有返回值,我们称为无参无返回值的方法. 方法的使用分两步: 第一步,定义方法 例如:下面代码定义了一个方法名 ... 
- 使用 jQuery Deferred 和 Promise 创建响应式应用程序
		这篇文章,我们一起探索一下 JavaScript 中的 Deferred 和 Promise 的概念,它们是 JavaScript 工具包(如Dojo和MochiKit)中非常重要的一个功能,最近也首 ... 
- Java 中无参无返回值方法的使用
		如果方法不包含参数,且没有返回值,我们称为无参无返回值的方法. 方法的使用分两步: 第一步,定义方法 例如:下面代码定义了一个方法名为 show ,没有参数,且没有返回值的方法,执行的操作为输出 “ ... 
- Win32 多线程的创建方法和基本使用
		Win32多线程的创建方法主要有: (1)CreateThread() (2)_beginthread()&&_beginthreadex() (3)AfxBeginThread() ... 
随机推荐
- Tensorflow中卷积的padding方式
			根据tensorflow中的Conv2D函数,先定义几个基本符号: 输入矩阵W*W,这里只考虑输入宽高相等的情况,如果不相等,推导方法一样 filter矩阵F*F,卷积核 stride值S,步长 输出 ... 
- Python 读取写入配置文件 —— ConfigParser
			Python 读取写入配置文件 —— ConfigParser Python 读取写入配置文件很方便,可使用内置的 configparser 模块:可查看源码,如博主本机地址: “C:/python2 ... 
- POJ3070:Fibonacci(矩阵快速幂模板题)
			http://poj.org/problem?id=3070 #include <iostream> #include <string.h> #include <stdl ... 
- 如何使用代码备份SQL Server数据库
			1.添加引用 using Microsoft.SqlServer.Management.Smo; using Microsoft.SqlServer.Management.Common; 2. Bac ... 
- springcloud18---springCloudConfig
			package com.itmuch.cloud; import org.springframework.beans.factory.annotation.Value; import org.spri ... 
- 20135320赵瀚青LINUX期中总结
			期中总结 心得与体会 本学期的LINUX内核这门课程已经进行了一半,这门课的学习方法和上个学期深入理解计算机系统的方式差不多,所以也没有特别多不适应,LINUX内核在我看来,就是理解一个操作系统是如何 ... 
- 20162311 课堂测试   泛型类—Bag
			课堂测试 泛型类-Bag 目录 一.题目要求 二.设计思路 三.问题和解决办法 四.代码运行截图 五.代码托管地址 六.总结 一.题目要求 题目:泛型类-Bag 返回目录 二.设计思路 自定义一个Ba ... 
- 从头到尾测地理解KMP算法【转】
			本文转载自:http://blog.csdn.net/v_july_v/article/details/7041827 1. 引言 本KMP原文最初写于2年多前的2011年12月,因当时初次接触KMP ... 
- 【熊猫TV】《程序员》:聚光灯下的熊猫TV技术架构演进
			2015年开始的百播大战,熊猫TV是其中比较特别的一员. 说熊猫TV是含着金钥匙出生的公子哥不为过.还未上线,就频频曝光,科技号,微博稿,站上风口浪尖.内测期间更是有不少淘宝店高价倒卖邀请码,光内测时 ... 
- Mininet实验 测量路径损耗率
			参照:基于Mininet测量路径的损耗率 在SDN环境中,可以利用控制器来测量特定路径的损耗率,在本实验中,基于Mininet脚本,设置特定的交换机间的路径损耗速率,然后编写POX脚本,实现对路径的损 ... 
