目录: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获取对象 getelementbyid怎么用_getelementbyid获取对象

△ 图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获取对象 getelementbyid怎么用_jQuery_02

△ 图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获取对象 getelementbyid怎么用_工厂设计模式_03

△ 图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获取对象 getelementbyid怎么用_jQuery_04

△ 图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获取对象 getelementbyid怎么用_getelementbyid什么意思_05

△ 图5_原生JS的DOM转为JQ对象

思考题:那如果selector是一个字符串,那段代码是啥意思呢?if(typeof selector === "string") {....} 这里的代码啥意思呢?

还有一种$(document.body).get(0),咱去找原型上的get方法源码:

getelementbyid获取对象 getelementbyid怎么用_getelementbyid获取对象_06

△ 图6_$('*').get()方法:将JQ对象转为原生JS的对象

(3)get和eq方法的区别

getelementbyid获取对象 getelementbyid怎么用_getelementbyid什么意思_07

△ 图7_get方法和eq的区别

(4)each方法

getelementbyid获取对象 getelementbyid怎么用_getelementbyid什么意思_08

△ 图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?