从jQuery源码理解jQuery插件的实现机制
基于jQuery源码学习jQuery中的插件实现机制,进一步加深对JS和Bootstrap中tooltip的理解。
--By Brisk Yu
(function( window, undefined ) { var jQuery = (function() { var jQuery = function( selector, context ) { return new jQuery.fn.init( selector, context, rootjQuery ); },
//。。。
;
jQuery.fn = jQuery.prototype = { constructor: jQuery, init: function(selector, context, rootjQuery){ //。。。 }, length: 0 //。。。 }; jQuery.fn.init.prototype = jQuery.fn; return jQuery; })(); window.jQuery = window.$ = jQuery; })(window);
首先学习jQuery 1.7 中的选择器实现源码。
(function( window,undefined ) { })(window);
此处的function是一个匿名函数,可以理解为将window作为参数传递给function。function外的()的作用是让JS解释器将该条语句视为一个表达式[2]。JS解释器运行至此会执行function函数,并将函数执行的结果传给第二行的jQuery对象。undefined是Undefined类型唯一的值,此处作用是兼容不认识undefined的旧浏览器[1]。
var jQuery = function( selector, context ) { return new jQuery.fn.init( selector, context, rootjQuery ); }
该函数实现jQuery的选择器功能,因此我们可以认为$('[data-toggle="tooltip"]')即是 new jQuery.fn.init( '[data-toggle="tooltip"]'), context, rootjQuery) ,将init函数实例化的对象传递给第三行的jQuery对象。这两个jQuery对象其实是一样的,第三行的jQuery对象会在最后当作方法的返回值传递给第二行的jQuery对象。
接下来,jQuery.fn.init方法体定义在:
jQuery.fn = jQuery.prototype = { constructor: jQuery, init: function(selector, context, rootjQuery){ //实际生成jQuery对象的代码 }, length: 0 //杂七杂八项 };
在jQuery中,有且仅有函数具有prototype属性[3]。当创建函数时,JS会为这个函数自动添加prototype属性,值是一个具有 constructor 属性的对象。而一旦将这个函数当作构造函数(constructor)调用(即通过new关键字调用),那么JS就会帮你创建该构造函数的实例,实例继承构造函数prototype的所有属性和方法[3]。
jQuery.fn.init.prototype = jQuery.fn;
到这里思路就很清晰了,将 jQuery.fn与jQuery.fn.init的prototype对应。(暂时不太明白这样写的用意,可能是为了简化代码?)这样写完便可以在代码中用jQuery.fn来为init添加prototype。此时,如果我们向jQuery.fn添加函数时,其实便是向jQuery.fn.init的prototype添加该函数。因此init实例化后的对象便可以执行添加的函数。而末尾的window.jQuery = window.$ = jQuery方便我们可以在代码中用“$”来代替“jQuery”。
此时再看Bootstrap中tooltip实现的源码:
$.fn.tooltip = function (option) { return this.each(function () { var $this = $(this) var data = $this.data('bs.tooltip') var options = typeof option == 'object' && option if (!data) $this.data('bs.tooltip', (data = new Tooltip(this, options))) if (typeof option == 'string') data[option]() }) }
这里向jQuery对象的fn.init的prototype添加了一个tooltip属性,该属性指向一个方法。因此我们可以在JS中通过$('[data-toggle="tooltip"]').tooltip()打开提示框。
参考资料:
[1] https://blog.csdn.net/yanyan19880509/article/details/7339900
[2] https://swordair.com/function-and-exclamation-mark/
[3] https://github.com/creeperyang/blog/issues/9