在第一篇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. angular ui-route

    http://www.cnblogs.com/freeliver54/p/4488141.html

  2. Unity3D资源存放笔记

    文件夹及路径 昨天记了一篇AssetBundle学习笔记,那么游戏中的各种资源应该如何存放呢? 在网上一阵搜罗,把笔记记一下. 非特殊名称文件夹 非Unity3D指定名称的文件夹中的资源,如果游戏场景 ...

  3. 【C++深入浅出】设计模式学习之简单工厂

    看大话设计模式中大牛对小菜的精辟点评,也写了一个计算器程序,并跟着点评一路改良,还是不过瘾,应用了类模板和异常捕捉机制重写了程序. 本文不能算干货,恰当的比方是饭前甜点,吃一口有点味.有点意思,总归太 ...

  4. android studio 真机调试

    1.使用usb连接电脑,打开开发者选项,打开usb调试. 2.不能使用仅充电,修改为媒体设备(MTP) 3.如果无法连接可以使用豌豆荚或者金山手机助手连接. 4.运行android程序即可. 5.如果 ...

  5. 博客转移到lyso.me

    博客转移到http://lyso.me :)

  6. Java算法试题--猜字母/杀人游戏

    题目例如以下: 把abcd-s共19个字母组成的序列反复拼接106次,得到长度为2014的串. 接下来删除第1个字母(即开头的字母a).以及第3个,第5个等全部奇数位置的字母. 得到的新串再进行删除奇 ...

  7. android126 zhihuibeijing 极光推送

    https://www.jpush.cn/ 张三把消息发送给自己的服务器,自己的服务器将消息发送给极光推送,然后极光推送将消息发送给妹子. 清单文件: <?xml version="1 ...

  8. careercup-中等难题 17.2

    17.2 设计一个算法,判断玩家是否赢了井字游戏. 解法: 假设这个检查某人是否赢得了井字游戏的函数为HasWon,那么我们第一步要向面试官确认, 这个函数是只调用一次,还是要多次频繁调用.如果是多次 ...

  9. Android 自定义View修炼-自定义弹幕效果View

    一.概述 现在有个很流行的效果就是弹幕效果,满屏幕的文字从右到左飘来飘去.看的眼花缭乱,看起来还蛮cool的 现在就是来实现这一的一个效果,大部分的都是从右向左移动漂移,本文的效果中也支持从左向右的漂 ...

  10. 读取Log日志并打印到sdcard

    @SuppressLint("SimpleDateFormat") private static SimpleDateFormat sdf = new SimpleDateForm ...