天天看點

getelementbyid什麼意思_同僚問我這段代碼什麼意思? | 工廠設計模式 | 跟着jQuery大佬學程式設計思想...

▲ 點選上方藍字關注我 ▲

文 / 景朝霞

來源公号 / 朝霞的光影筆記

ID / zhaoxiajingjing

目錄:0 / moment庫1 / 工廠設計模式(1)問個問題(2)隻看factory(global)在浏覽器下的運作2 / jQuery中常用的方法(1)$(document).read() (2)JQ擷取的對象和原生JS擷取的對象(3)get和eq方法的差別(4)each方法3 / 代碼

0 / moment庫

API:http://momentjs.cn/docs/

我們的項目裡面用到moment.js這個庫來處理日期,有一天旁邊的同僚翻着這段源碼問我啥意思:

getelementbyid什麼意思_同僚問我這段代碼什麼意思? | 工廠設計模式 | 跟着jQuery大佬學程式設計思想...

△ 圖1_moment.js的源碼

咱之前看過jQuery的源碼,再來看這個是不是輕松很多啦~

好,繼續來讀jQuery的源碼,跟着jQuery大佬學程式設計思想

1 / 工廠設計模式

(1)問個問題

var a = $(); console.log(a instanceof jQuery); //=> true var b = $('div'); console.log(b instanceof jQuery); //=> true
           

△ object instanceof constructor

instanceof

運算符用來檢測

constructor.prototype

是否存在于

object

的原型鍊上

問題來了:這裡沒有使用

new jQuery()

為什麼

$()

出來的就是jQuery的執行個體呢?

我看的jQuery的最新版本

3.5.1

getelementbyid什麼意思_同僚問我這段代碼什麼意思? | 工廠設計模式 | 跟着jQuery大佬學程式設計思想...

△ 圖2_jQuery的源碼

(2)隻看factory(global)在浏覽器下的運作

拆了簡化的出來的,可以對照源碼檢視哈~

function factory(window, noGlobal) {     var version = "3.5.1",         jQuery = function (selector, context) {             return new jQuery.fn.init(selector, context);         };     jQuery.fn = jQuery.prototype = {         jquery: version,         constructor: jQuery     };      var rootjQuery,         rquickExpr = /^(?:\s*()[^>]*|#([\w-]+))$/,         init = jQuery.fn.init = function (selector, context, root) {             //...CDOE         };      init.prototype = jQuery.fn;      if (typeof noGlobal === "undefined") {         window.jQuery = window.$ = jQuery;     } }  factory(window);
           

△ 從jQuery源碼粘貼出來的

$() 這就是把jQuery方法執行:作為普通函數執行(JQ的選擇器),但是最後得到的結果是jQuery類的執行個體對象

$('.box')

jQuery('.box')

是怎麼建立jQuery的執行個體對象的呢?

getelementbyid什麼意思_同僚問我這段代碼什麼意思? | 工廠設計模式 | 跟着jQuery大佬學程式設計思想...

△ 圖3_簡圖

從面向對象角度可以看出,

$()

jQuery()

調用了jQuery函數時,傳回了一個執行個體對象:new jQuery.fn.init()

而,jQuery.prototype 和 jQuery.fn.init.prototype 是一個原型對象

$()

可以不使用new操作符就能得到jQuery的執行個體對象

工廠設計模式,抽象了建立具體對象的過程。

2 / jQuery中常用的方法

提問:

1、不用new操作符如何快速的建立Fn函數的一個執行個體對象?

2、

$(document).read(function (){} )

$(function(){})

的差別?

3、原生JS擷取的DOM元素集合與JQ擷取的集合怎麼互相轉換?

4、JQ的get方法和eq方法的差別?

5、JQ的each方法怎麼實作的?

(1)$(document).read()

$(document).read(function (){})

$(function (){})

有差別嗎?

getelementbyid什麼意思_同僚問我這段代碼什麼意思? | 工廠設計模式 | 跟着jQuery大佬學程式設計思想...

△ 圖4_差別

$(document).ready(函數)

裡面的ready方法監聽了DOMContentLoaded事件

$(function (){     // 等待頁面中的DOM結構渲染完成後,去執行回調函數 });
           

(2)JQ擷取的對象和原生JS擷取的對象

//=>由原生JS擷取的DOM元素 var box = document.getElementById('box'); //=> 由JQ擷取的執行個體對象 var $box = $('#box');
           

△ 擷取元素

他們兩種擷取的對象之間的方法是不能混着調用的,需要切換才可以:

① 原生=>JQ,

$(原生對象)

,即:

$(box)

類數組集合

② JQ=>原生,

$xxx[0]

,即:

$box[0]

或者

$box.get(0)

怎麼實作的呢?看源碼:

getelementbyid什麼意思_同僚問我這段代碼什麼意思? | 工廠設計模式 | 跟着jQuery大佬學程式設計思想...

△ 圖5_原生JS的DOM轉為JQ對象

思考題:那如果selector是一個字元串,那段代碼是啥意思呢?

if(typeof selector === "string") {....}

這裡的代碼啥意思呢?

還有一種

$(document.body).get(0)

,咱去找原型上的get方法源碼:

getelementbyid什麼意思_同僚問我這段代碼什麼意思? | 工廠設計模式 | 跟着jQuery大佬學程式設計思想...

△ 圖6_$('*').get()方法:将JQ對象轉為原生JS的對象

(3)get和eq方法的差別

getelementbyid什麼意思_同僚問我這段代碼什麼意思? | 工廠設計模式 | 跟着jQuery大佬學程式設計思想...

△ 圖7_get方法和eq的差別

(4)each方法

getelementbyid什麼意思_同僚問我這段代碼什麼意思? | 工廠設計模式 | 跟着jQuery大佬學程式設計思想...

△ 圖8_JQ的each方法

isArrayLike

方法:見名知意,判斷是否為類數組,那源碼怎麼寫的呢?自己翻翻看

for in

循環處理對象,3個注意點:

① 可以周遊到原型上咱自己擴充的公共的屬性

② 數字的順序(這個咱控制不了)

③ 無法找到symbol的屬性

好,改造一下:

var keys = Object.kesy(obj) typeof Symbol !== 'undefined' ? keys = kyes.concat(Object.getOwnPropertySymbols(obj)) : null; for(; i < keys.length; i++){     var key = keys[i];     if(callback.call(obj[key], key, obj[key] === false)) {         break;     } }
           

3 / 代碼

function factory(window, noGlobal) {     var arr = [];     var slice = arr.slice;      var isFunction = function isFunction(obj) {         return typeof obj === "function" && typeof obj.nodeType !== "number";     };      function isArrayLike(obj) {          // Support: real iOS 8.2 only (not reproducible in simulator)         // `in` check used to prevent JIT error (gh-2145)         // hasOwn isn't used here due to false negatives         // regarding Nodelist length in IE         var length = !!obj && "length" in obj && obj.length,             type = toType(obj);          if (isFunction(obj) || isWindow(obj)) {             return false;         }          return type === "array" || length === 0 ||             typeof length === "number" && length > 0 && (length - 1) in obj;     }      var         version = "3.5.1",         // Define a local copy of jQuery         jQuery = function (selector, context) {              // The jQuery object is actually just the init constructor 'enhanced'             // Need init if jQuery is called (just allow error to be thrown if not included)             return new jQuery.fn.init(selector, context);         };      jQuery.fn = jQuery.prototype = {         jquery: version,         constructor: jQuery,         length: 0,          // Get the Nth element in the matched element set OR         // Get the whole matched element set as a clean array         get: function (num) {              // Return all the elements in a clean array             if (num == null) {                 return slice.call(this);             }              // Return just the one element from the set             return num < 0 ? this[num + this.length] : this[num];         },         eq: function (i) {             var len = this.length,                 j = +i + (i < 0 ? len : 0);             return this.pushStack(j >= 0 && j < len ? [this[j]] : []);         },         // Take an array of elements and push it onto the stack         // (returning the new matched element set)         pushStack: function (elems) {              // Build a new jQuery matched element set             var ret = jQuery.merge(this.constructor(), elems);              // Add the old object onto the stack (as a reference)             ret.prevObject = this;              // Return the newly-formed element set             return ret;         },          // Execute a callback for every element in the matched set.         each: function (callback) {             return jQuery.each(this, callback);         }     };      jQuery.extend = jQuery.fn.extend = function () {         // 把方法擴充到jQuery對象上、jQuery.fn上     };      jQuery.extend({         each: function (obj, callback) {             var length, i = 0;              if (isArrayLike(obj)) {                 length = obj.length;                 for (; i < length; i++) {                     if (callback.call(obj[i], i, obj[i]) === false) {                         break;                     }                 }             } else {                 for (i in obj) {                     if (callback.call(obj[i], i, obj[i]) === false) {                         break;                     }                 }             }              return obj;         }     });      var rootjQuery,          // A simple way to check for HTML strings         // Prioritize #id over  to avoid XSS via location.hash (#9521)         // Strict HTML recognition (#11290: must start with          // Shortcut simple #id case for speed         rquickExpr = /^(?:\s*()[^>]*|#([\w-]+))$/,          init = jQuery.fn.init = function (selector, context, root) {             var match, elem;              // HANDLE: $(""), $(null), $(undefined), $(false)             if (!selector) {                 return this;             }              // Method init() accepts an alternate rootjQuery             // so migrate can support jQuery.sub (gh-2101)             root = root || rootjQuery;              // Handle HTML strings             if (typeof selector === "string") {                 if (selector[0] === " &&                     selector[selector.length - 1] === ">" &&                     selector.length >= 3) {                      // Assume that strings that start and end with <> are HTML and skip the regex check                     match = [null, selector, null];                  } else {                     match = rquickExpr.exec(selector);                 }                  // Match html or make sure no context is specified for #id                 if (match && (match[1] || !context)) {                      // HANDLE: $(html) -> $(array)                     if (match[1]) {                         context = context instanceof jQuery ? context[0] : context;                          // Option to run scripts is true for back-compat                         // Intentionally let the error be thrown if parseHTML is not present                         jQuery.merge(this, jQuery.parseHTML(                             match[1],                             context && context.nodeType ? context.ownerDocument || context : document,                             true                         ));                          // HANDLE: $(html, props)                         if (rsingleTag.test(match[1]) && jQuery.isPlainObject(context)) {                             for (match in context) {                                  // Properties of context are called as methods if possible                                 if (isFunction(this[match])) {                                     this[match](context[match]);                                      // ...and otherwise set as attributes                                 } else {                                     this.attr(match, context[match]);                                 }                             }                         }                          return this;                          // HANDLE: $(#id)                     } else {                         elem = document.getElementById(match[2]);                          if (elem) {                              // Inject the element directly into the jQuery object                             this[0] = elem;                             this.length = 1;                         }                         return this;                     }                      // HANDLE: $(expr, $(...))                 } else if (!context || context.jquery) {                     return (context || root).find(selector);                      // HANDLE: $(expr, context)                     // (which is just equivalent to: $(context).find(expr)                 } else {                     return this.constructor(context).find(selector);                 }                  // HANDLE: $(DOMElement)             } else if (selector.nodeType) {                 this[0] = selector;                 this.length = 1;                 return this;                  // HANDLE: $(function)                 // Shortcut for document ready             } else if (isFunction(selector)) {                 return root.ready !== undefined ?                     root.ready(selector) :                      // Execute immediately if ready is not present                     selector(jQuery);             }              return jQuery.makeArray(selector, this);         };      // Give the init function the jQuery prototype for later instantiation     init.prototype = jQuery.fn;      // Initialize central reference     rootjQuery = jQuery(document);       if (typeof noGlobal === "undefined") {         window.jQuery = window.$ = jQuery;     } }  factory(window);
           

△ 從jQuery中粘貼的

- end -

提問:

1、不用new操作符如何快速的建立Fn函數的一個執行個體對象?

2、

$(document).read(function (){} )

$(function(){})

的差別?

3、原生JS擷取的DOM元素集合與JQ擷取的集合怎麼互相轉換?

4、JQ的get方法和eq方法的差別?

5、JQ的each方法怎麼實作的?

思考題:如何判斷是類數組isArrayLike?

getelementbyid什麼意思_同僚問我這段代碼什麼意思? | 工廠設計模式 | 跟着jQuery大佬學程式設計思想...

從"你"到"更好的你",有無限可能~