jQuery 源码学习 - 01 - 简洁的 $('...')
首先贴上学习参考资料:【深入浅出jQuery】源码浅析--整体架构,备用地址:
(function(params) { // ... })(Variable)
好处很多,就不介绍,感兴趣的请移步 google/baidu。
2.为什么没有 new ?
js 与 java 很像,都是面向对象的语言,因此,这意味这在 js 中我们需要通过 new 运算符来新建一个对象。当年面试的时候有一个问题是 jQuery 对象与普通的 dom 对象有什么不同,jQuery 对象不需要显式地 new 出来也是一个答案。
为什么不需要 new 呢?
var jQuery = function(selector, context) { // 这里是为什么使用时无须 new 的原因 return new jQuery.fn.init(selector, context, rootjQuery); },
因为在内部已经帮我们 new 了。
我们通常是 $('xxx') 来获取一个 jQuery 对象,其实内部执行的就是 jQuery() 函数,这个函数返回一个对象,即 new jQuery.fn.init(selector, context, rootjQuery) 。
var jQuery.fn = jQuery.prototype = { // 实例化方法,也是所有 jQuery 对象的构造器 init: function(selector, context, rootjQuery) { // .... } }
这一句,手动指定 jQuery 的 prototype(关于 js 函数的 prototype,请移步 google/baidu, 或者 JS 中的原型 -- prototype、__proto__ 以及原型链),同时,声明一个jQuery.fn 对象,缓存也好,定义也好,以待后用。
jQuery.fn.init.prototype = jQuery.fn;
这一句很关键,也很重要,作用是传递原型,确保 jQuery 对象中的 this 指向正确。接下来一步一步分析思想。
在分析之前我们先进行一下扩写,方便理解:
jQuery.fn.init.prototype = jQuery.fn = jQuery.prototype;
这里手动指定 jQuery.fn.init 函数的原型是 jQuery.fn,而因为上一句 jQuery.fn = jQuery.prototype ,所以,就确保了 jQuery.fn.init 函数的原型就是 jQuery 的原型,这意味着, jQuery.fn.init 与 jQuery 是等价的,因此,先不管具体实现,通过 new jQuery.fn.init(selector, context, rootjQuery) 出来的对象本质上就是 jQuery 对象,这样,就能够通过 this 访问到 jQuery.fn(或者 jQuery 原型)上的所有方法和属性。
套用大佬的总结:
最后,不要忘了把 jQuery 挂到 window 上:
window.jQuery = window.$ = jQuery;
贴一个简单的实践:
(function(window, undefined) { var jQuery = function() { return new jQuery.fn.init(); } jQuery.fn = jQuery.prototype = { init: function() { console.log('init', this); return this;}, add: function() { console.log('add'); }, remove: function() { console.log('remove'); } } jQuery.fn.init.prototype = jQuery.prototype; window.jQuery = window.$ = jQuery; })(window)