在第一篇jQuery源码分析中,简单分析了jQuery对象的构造过程,里面提到了jQuery.fn、jQuery.prototype、jQuery.fn.init.prototype的关系。

  从代码中可以看出,这三者其实都是等价的,都是指向了jQuery.prototype,但这又是为什么呢?为什么要这么绕?一个jQuery.prototype不就解决问题了吗?带着这些疑问,再一次来看看其中的精妙之处。
 

  jQuery构造器

  jQuery使用非常方便,其中一个原因就是我们在调用的时候并不需要使用关键字new来创造一个jQeury对象,直接使用jQuery("#id")或$(".class")就可轻松得到一个新的jQuery对象。原因就是jQuery使用工厂方法,利用构造器创造一个新的jQuery对象并返回,省去了用户的new操作。

 

    一般构造器

     一般情况下,我们在JavaScript中创建一个类的时候,会这样做:
 var $ = jQuery = function() {
return new jQuery();
}
jQuery.prototype = {
jquery: "1.11"
};
console($().jquery);

  上面的代码有些奇怪,因为一个构造器返回利用它自身创建了一个新的对象并返回,这样形成了一个死循环,产生栈溢出的异常。因此,上面的代码是错误的代码。

 返回原型方法 jQuery.fn.init

  为了解决循环,就必须在jQuery.prototype中定义的一个构造器,这就是jQuery.fn.init了。
  jQeury.fn实际上就是jQuery.prototype的别名,我认为这个别名的目的就为了说明prototype上挂载的都是jQuery类的公有方法,同时也缩减了引用jQuery.prototype时要书写的代码长度。
     jQuery.fn.init能够返回jQuery.fn这个原型方法,代码是:
 var $ = jQuery = function() {
return jQuery.fn.init();
}
jQuery.fn = jQuery.prototype = {
init: function(){
return this;
},
jquery: "1.11"
}
console.log($().jquery);
console.log($()); // 将jQuery.prototype打印出来, Object { init: jQuery.prototype.init(), jquery: "1.11"}

  虽然这个方法解决了嵌套为问题,也将jQuery的原型方法传递给了jQuery对象,但它是将一个完整的jQuery.prototype暴露处理,jQuery的任何对this关键字的操作,实际上就是直接在jQuery.prototype上进行操作,那么jQuery.fn的完整性很容易就被破坏了,jQuery对象之间也可能产生不可预估的影响。

     如:
 console.log($().jquery);     // 1.11
$().jquery = '2.1';
console.log($().jquery); // 2.1

返回一个jQuery.fn.init对象

  为了避免直接返回jQuery.fn,我们需要借鉴一开始使用关键字new的方法,通过new创建一个新Oject,改变了this所指向的对象,从而避开对jQuery.fn的直接暴露。
 var $ = jQuery = function() {
return new jQuery.fn.init();
}
jQuery.fn = jQuery.prototype = {
init: function(){
this.num = 2015;
return this;
},
jquery: "1.11"
} console.log($().num); //
console.log($().jquery); // undefined
console.log($()); // Object {num: 2015}

  但此时问题来了,new jQuery.fn.init()所返回的新对象并没有继承jQuery.fn,因为jQuery.fn.init.prototype仅仅是指向了一个function对象的原型,并不包含jQuery.fn。这时,是彻底地将jQuery.fn给封锁了起来。

让jQuery.fn.init.prototype指向jQuery.fn

     既然jQuery.fn.init.prototype只是指向了Object.prototype,那么我们只需要改变它的指向,让它指向jQuery.fn不就好了吗?

 var $ = jQuery = function(x) {
return new jQuery.fn.init(x);
}
jQuery.fn = jQuery.prototype = {
init: function(x){
this.num = x || 0;
return this;
},
jquery: "1.11"
}
jQuery.fn.init.protoytpe = jQuery.fn; console.log($(2015).num); //
console.log($(2015).jquery); // 1.11
console.log($(2016).num); //
console.log($(2016).__proto__); // Object { init: jQuery.prototype.init(), jquery: "1.11" }

  显然,jQuery.fn.init这个工厂方法完全奏效了,$()返回的每个对象,都拥有独立的内部变量,也共享jQuery.fn上的公有方法和属性。

  总结  

  到这里,相信这个三个特殊的名字存在的意义就非常明了了。
  • jQuery.prototype,挂载jQuery对象的原型方法;
  • jQuery.fn是jQuery.prototype的别名,标注jQuery.prototype的意义且缩短代码书写长度,避免混淆(像jQuery.prototype.init.prototype = jQuery.prototype这行代码,能把人看昏了)方便使用;
  • jQuery.fn.init.prototype,则是为了让jQuery.fn.init这个工厂方法能够继承jQuery.fn上的原型方法。
  虽然三个特殊的名字都代表了同样一个东西,但他们的意义并不相同,因此需要特别注意这一点。

  参考书:朱印宏 《jQury内核详解与实战》

jQuery 源码分析 8: 回头看jQuery的构造器(jQuery.fn,jQury.prototype,jQuery.fn.init.prototype的分析)的更多相关文章

  1. jquery源码分析之一前言篇

    1.问:jquery源码分析的版本是什么? 答:v3.2.1 2.问:为什么要分析jquery源码? 答:javascript是一切js框架的基础,jquery.es6.vue.angular.rea ...

  2. Jquery源码分析与简单模拟实现

    前言 最近学习了一下jQuery源码,顺便总结一下,版本:v2.0.3 主要是通过简单模拟实现jQuery的封装/调用.选择器.类级别扩展等.加深对js/Jquery的理解. 正文 先来说问题: 1. ...

  3. 分析jQuery源码时记录的一点感悟

    分析jQuery源码时记录的一点感悟      1.  链式写法      这是jQuery语法上的最大特色,也许该改改POJO里的set方法,和其他的非get方法什么的,可以把多行代码合并,减去每次 ...

  4. 菜鸟的jQuery源码学习笔记(前言)

    前言 相信任何一名前端开发人员或者是前端爱好者都对jQuery不陌生.jQuery简单易用,功能强大,特别是拥有良好的浏览器兼容性,大大降低了前端开发的难度,使得前端开发变得“平易近人起来”.自从本人 ...

  5. jQuery源码浅析2–奇技淫巧

    最近一直在研读 jQuery 源码,初看源码一头雾水毫无头绪,真正静下心来细看写的真是精妙,让你感叹代码之美. 其结构明晰,高内聚.低耦合,兼具优秀的性能与便利的扩展性,在浏览器的兼容性(功能缺陷.渐 ...

  6. jquery源码学习-构造函数(2)

    最近几天一直在研究jquery源码,由于水平太低看得昏头转向.本来理解的也不是很深刻,下面就用自己的想法来说下jquery是如何定义构造函数初始化的.如果有什么不对的地方,希望个位高手指出.  一般写 ...

  7. jquery源码学习-初始(1)

    最近几天一直在研究jquery源码,由于水平太低看得昏头转向.本来理解的也不是很深刻,下面就用自己的想法来说下jquery是如何定义构造函数初始化的.如果有什么不对的地方,希望个位高手指出. 首先要了 ...

  8. 01- ES6、jquery源码、node、webpack

    1.课程介绍 小马哥blog:https://www.cnblogs.com/majj/ 前端学习路径:https://www.processon.com/view/link/5d3a5947e4b0 ...

  9. jQuery源码分析系列

    声明:本文为原创文章,如需转载,请注明来源并保留原文链接Aaron,谢谢! 版本截止到2013.8.24 jQuery官方发布最新的的2.0.3为准 附上每一章的源码注释分析 :https://git ...

随机推荐

  1. UVA 10806 Dijkstra, Dijkstra.(费用流)

    n个点的无向带权图,求1->n的最短往返路径,不走重复边. 这里涉及到一个知识点:求无向图上s->t的最短路,其实就是费用流. 而求1->n最短往返路径呢?增加源点s,由s到1加弧, ...

  2. 【Stage3D学习笔记续】真正的3D世界(三):纹理效果

    混合模式: 代码 示例是<Stage3D指南>中的直接弄出来的,可以通过点击键盘上的Q.W.E这3个按键,更换混合模式.模型和纹理,可以直观的查看不同混合模式的效果,住:下方的地形使用&q ...

  3. Windows下如何检测用户修改了系统时间并且把系统时间改回来

    博客搬到了fresky.github.io - Dawei XU,请各位看官挪步.最新的一篇是:Windows下如何检测用户修改了系统时间并且把系统时间改回来.

  4. 怎样在Java中实现基本数据类型与字符之间的转换

    摘要:在我们对Java的学习当中数据类型之间的转换,是我们常见的事,我们也都知道基本数据类型之间有自动转换和强制转换,在int   . short  . long .float .double之间的转 ...

  5. 获利能力分析COPA的BAPI:BAPI_COPAACTUALS_POSTCOSTDATA 通过增强返回凭证号

    用这个BAPI:BAPI_COPAACTUALS_POSTCOSTDATA 记录销售成本的时候,发现不能return生产的co凭证号,利用内存应该是最好的方法. SCN上的帖子:https://blo ...

  6. SpringMVC 参考文档

    原文地址:http://blog.csdn.net/lufeng20/article/details/7598801

  7. SCOM2012端口需求

    Agent push requirements (including firewall ports): The account being used to push the agent must ha ...

  8. Codeforces Round #200 (Div. 1)A. Rational Resistance 数学

    A. Rational Resistance Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/contest/343 ...

  9. java_spring_List,Map,Properties,Set注入与遍历

    package com.dao.bean.www; import java.util.List; import java.util.Map; import java.util.Properties; ...

  10. arcgis 绝对、相对、UNC 和 URL

    您每天都通过路径浏览至数据和工具箱.在共享数据和工具之前,您对此可能没有做太多考虑,其实您也无需考虑.本部分将详细讨论以下方面内容:路径.定义不同类型的路径以及 ArcGIS 对路径的管理方式. 路径 ...