jQuery源码分析

  1. (function (global, factory) {
  2. "use strict"
  3. /*
  4. global:在浏览器&webpack环境下,global是window,在Node环境下,global是Global全局对象/模块
  5. factory:传递的callback
  6. */
  7. if (typeof module === "object" && typeof module.exports === "object") {
  8. // JQ代码是在支持CommonJS规范「Node&Webpack」的环境下运行
  9. module.exports = global.document ?
  10. // 在webpack环境下运行:把 factory 执行的结果,基于 module.exports 导出
  11. // --> module.exports = jQuery
  12. // --> const $ = require('jquery') $就是导出的这个jQuery函数
  13. factory(global, true) :
  14. // 在Node环境下运行:JQ是不支持在Node环境下运行的
  15. // --> const $ = require('jquery')
  16. // --> $('box')
  17. function (w) {
  18. if (!w.document) {
  19. throw new Error("jQuery requires a window with a document");
  20. }
  21. return factory(w);
  22. }
  23. } else {
  24. // 在浏览器端运行:把factory执行
  25. // --> <script src='js/jquery.min.js'>
  26. factory(global)
  27. }
  28. })(
  29. typeof window !== "undefined" ? window : this,//这里可看下图 node环境下无window
  30. //==========================================↗↗↗↗↗↗↑↑↑↑↑↑↑↑↑↑↑↑↑↖↖↖↖↖↖↖
  31. function (window, noGlobal) {
  32. /*
  33. 进入这里只有两种情况:
  34. 1. 在浏览器下运行
  35. window->window对象
  36. noGlobal->undefined
  37. 2. 在webpack下运行
  38. window->window对象
  39. noGlobal->true
  40. */
  41. "use strict"
  42. /* 构造函数 */
  43. var jQuery = function (selector, context) {
  44. return new jQuery.fn.init(selector, context)
  45. }
  46. jQuery.fn = jQuery.prototype = {
  47. constructor: jQuery,
  48. // ...
  49. }
  50. var init = jQuery.fn.init = function (selector, context, root) {
  51. // ...
  52. }
  53. init.prototype = jQuery.fn
  54. /*
  55. $() / jQuery() -> 创造 jQuery 类的实例「可以调用 jQuery.prototype 上提供的属性方法」
  56. 问题:它是如何做到,把函数当做普通函数执行(没有带new),最后还创建了自己这个类的一个实例?
  57. 它用到了“工厂设计模式「中转类」”
  58. + $() 首次创建的是 init 这个类的一个实例
  59. + init.prototype = jQuery.prototype
  60. + 创建的实例就相当于 jQuery 类的实例
  61. */
  62. /* 暴露API */
  63. // 对AMD模块化思想的支持
  64. if (typeof define === "function" && define.amd) {
  65. define("jquery", [], function () {
  66. return jQuery
  67. })
  68. }
  69. // 在浏览器下运行
  70. if (typeof noGlobal === "undefined") {
  71. window.jQuery = window.$ = jQuery
  72. }
  73. // 支持 webpack 基于 module.exports 导出
  74. return jQuery
  75. }
  76. )
  77. /*
  78. let arr = [10, 20, 30]
  79. arr.push(40)
  80. console.log(arr)
  81. */
  82. const push = [].push // Array.prototype.push
  83. let arr = [10, 20, 30]
  84. push.call(arr, 40)

K)BW`}0`}6IO`%GD5ZA4COF_tmb.jpg
![{29FR$UYHZZ5K1(F}LDI3B_tmb.jpg

仿照jQuery源码处理utils.js文件

  1. (function (global, factory) {
  2. "use strict"
  3. if (typeof module === 'object' && typeof module.exports === 'object') {
  4. //node or webpack environments
  5. module.exports = factory(global, true)
  6. return
  7. }
  8. //browser environments
  9. factory(global)
  10. })(
  11. typeof window !== "undefined" ? window : this,
  12. function factory(window, noGlobal) {
  13. "use strict"
  14. //检测是否为函数
  15. const isFunction = function isFunction(obj) {
  16. return typeof obj === 'function'
  17. }
  18. //笼统校验是否为对象
  19. const isObject = function isObject(obj) {
  20. return obj !== null && /^(object|function)$/.test(typeof obj)
  21. }
  22. // 获取对象所有私有成员「兼容到IE、不受枚举和类型的限制」
  23. const ownKeys = function ownKeys(obj) {
  24. if (!isObject(obj)) throw new TypeError('传递的obj不是一个对象')
  25. let keys = Object.getOwnPropertyNames(obj)
  26. if (typeof Symbol !== 'undefined') {
  27. keys = keys.concat(Object.getOwnPropertySymbols(obj))
  28. }
  29. return keys
  30. }
  31. //给对象新增一个不可枚举的成员(可删除可修改)
  32. const def = function define(obj, key, value) {
  33. Object.defineProperty(obj, key, {
  34. value,//"value":value | value:value
  35. writable: true,
  36. configurable: true,
  37. enumerable: false
  38. })
  39. }
  40. /* 暴露API */
  41. const utils = {
  42. isFunction,
  43. isObject,
  44. ownKeys,
  45. def
  46. }
  47. if (typeof define === "function" && define.amd) {
  48. define("utils", [], function () {
  49. return utils
  50. })
  51. }
  52. if (typeof noGlobal === "undefined") {
  53. window.utils = window._ = utils
  54. }
  55. return utils
  56. }
  57. )
  58. //检测是否为函数
  59. const isFunction = function isFunction(obj) {
  60. return typeof obj === 'function'
  61. }
  62. //笼统校验是否为对象
  63. const isObject = function isObject(obj) {
  64. return obj !== null && /^(object|function)$/.test(typeof obj)
  65. }
  66. //获取对象所有私有成员(兼容IE、不受枚举和类型限制)
  67. /* const ownKeys = function ownKeys(obj) {
  68. // 确保传递的是对象
  69. if (!isObject(obj)) throw new TypeError('传递的obj不是一个对象')
  70. // 验证是否支持Reflect
  71. if (typeof Reflect !== 'undefined') return Reflect.ownKeys(obj)
  72. return Object.getOwnPropertyNames(obj)
  73. } */
  74. // 获取对象所有私有成员「兼容到IE、不受枚举和类型的限制」
  75. const ownKeys = function ownKeys(obj) {
  76. if (!isObject(obj)) throw new TypeError('传递的obj不是一个对象')
  77. let keys = Object.getOwnPropertyNames(obj)
  78. if (typeof Symbol !== 'undefined') {
  79. keys = keys.concat(Object.getOwnPropertySymbols(obj))
  80. }
  81. return keys
  82. }
  83. //给对象新增一个不可枚举的成员(可删除可修改)
  84. const def = function define(obj, key, value) {
  85. Object.defineProperty(obj, key, {
  86. value,//"value":value | value:value
  87. writable: true,
  88. configurable: true,
  89. enumerable: false
  90. })
  91. }

image.png
image.pngimage.pngimage.png