咱们平时使用jQuery大概是这样:css
let $p = $('p'); $p.css('fontSize', '40px');
咱们生成jQuery实例对象后,就能够使用原型上的css(), html()等方法,这就体现了原型继承:由构造函数生成的实例对象,能够继承构造函数的原型对象上的属性和方法。html
咱们能够试着手写一个迷你的jQuery,思路大概是这样:node
1-经过匿名自执行函数来存放咱们的代码,将window对象做为参数传入,防止全局做用域的污染。jquery
2-利用工厂函数,在调用jQuery或者$的时候,返回构造函数的实例对象git
3-构造函数定义为jQuery.fn.init,初始化时处理dom元素,将dom元素绑定在实例对象上github
4-将构造函数的prototype属性指向jQuery.fn,此时构造函数的实例即可以继承jQuery.fn里的属性和方法dom
5-jQuery.fn是一个对象,里面存放了全部的jQuery方法,让外部来调用函数
代码实现:
完整代码请查看 my-jquery测试
// my-jquery.js (function(window) { var jQuery = function (selector) { // 经过new关键字,找到构造函数 return new jQuery.fn.init(selector); }; // 初始化 jQuery.fn jQuery.fn = jQuery.prototype = { constructor: jQuery, css: function(key, value) { let that = this; for (var i = 0; i < that.length; i++) { that[i].style[key] = value; } }, html: function (value) { return this[0].innerHTML; }, }; // 定义构造函数 var init = jQuery.fn.init = function(selector) { var slice = Array.prototype.slice; var dom = slice.call(document.querySelectorAll(selector)); var i, len = dom ? dom.length : 0; for (i = 0; i < len; i++) { this[i] = dom[i]; } this.length = len; this.selector = selector || ''; }; // 定义原型 init.prototype = jQuery.fn; window.$ = jQuery; })(window);
这里有个问题:这里为何不直接把init.prototype赋值为一个对象,而是要经过jQuery.fn作中转呢?this
jQuery.fn = {...}; init.prototype = jQuery.fn;
这就体现了原型的扩展性,jQuery.fn
| $.fn
是用来扩展插件用的,将插件扩展统一到$.fn.xxx
这一个接口,也是符合对修改封闭,对扩展开放的原则。
下面咱们来写一个简单的jQuery插件。
$.fn.getNodeName = function () { return this[0].nodeName; } // 测试 alert($box.getNodeName()); // DIV
小结:
本篇文章总结了如下几个问题