我們平時使用jQuery大概是這樣:
let $p = $('p');
$p.css('fontSize', '40px');
我們生成jQuery例項物件後,就可以使用原型上的css(), html()等方法,這就體現了原型繼承:由建構函式生成的例項物件,可以繼承建構函式的原型物件上的屬性和方法。
我們可以試著手寫一個迷你的jQuery,思路大概是這樣:
1-通過匿名自執行函式來存放我們的程式碼,將window物件作為引數傳入,防止全域性作用域的汙染。
2-利用工廠函式,在呼叫jQuery或者$的時候,返回建構函式的例項物件
3-建構函式定義為jQuery.fn.init,初始化時處理dom元素,將dom元素繫結在例項物件上
4-將建構函式的prototype屬性指向jQuery.fn,此時建構函式的例項便可以繼承jQuery.fn裡的屬性和方法
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做中轉呢?
jQuery.fn = {...};
init.prototype = jQuery.fn;
這就體現了原型的擴充套件性,jQuery.fn
| $.fn
是用來擴充套件外掛用的,將外掛擴充套件統一到$.fn.xxx
這一個介面,也是符合對修改封閉,對擴充套件開放的原則。
下面我們來寫一個簡單的jQuery外掛。
$.fn.getNodeName = function () {
return this[0].nodeName;
}
// 測試
alert($box.getNodeName()); // DIV
小結:
本篇文章總結了以下幾個問題
- jQuery是如何使用原型的?
- 如何實現一個小型的jQuery?
- jQuery的外掛擴充套件機制