# 分析源码学架构

#

# 读源码技巧

  • 不要试图一句一句读下去
  • 先理架构,再看入口,依流程读下去

# 读源码能给我们带来什么?

  • 优秀的架构和设计思维
  • 对于所用工具有更深的理解
  • 优秀的使用技巧

# jquery架构分析

  • 没有模块化时代的一个典型的架构代表

# 架构特点

  • 利用工厂模式,无new化构建对象
  • 模块划分明确
  • 开闭原则的优秀体现

# jquery技巧提炼

  • 优秀的参数处理(多态,健壮性)
    • 多态,可以支持多种参数
    • 健壮性,防止忘记传参数或者传错参数,导致报错
  • 模块化支持的检测

# 无模块化时代模块封装特点

  • 工具库或者类似jquery这样的单页面的库
  • 最外层是一个匿名自执行函数
  • 然后将window和undefined作为参数传入
    • js变量查找,有一个作用域链,优先在当前作用域查找,找不到的话, 会沿作用域链,逐级向上查找
    • 传入window,可以减少逐级向上查找的时间
    • undefined对于js来说,它是一个变量,而不是一个关键字,而null是一个关键字,所以不传null
  • 暴露的jquery并不是jquery的实例化对象,而是一个工厂模式的工厂方法, 而vue是直接把类暴露出去了
    • 这跟应用场景有关系,vue中有且只有一个根实例,全局只有一个new Vue()对象,其他的都是该对象的组件,所以vue需要对外暴露一个类
    • 工厂模式,本身是一个方法, 我调用这个方法,告诉这个方法我需要什么东西,这个方法把你要的东西给出来
    • 建立一个工厂方法,你只需要告诉这个工厂你要什么,他就会给你什么
    • 工厂方法特别适合于快速创建大量对象的情况,而jquery需要大量的创建DOM对象,所以用工厂模式更合适
  • 利用js引用类型的特点 jquery.prototype = jquery.prototype.init.prototype = jquery.fn 把这三个都指向jquery.prototype对象, 这样做修改时,只需要修改jquery.prototype对象即可,做到共享原型的效果
  • jquery的模块划分,是先实现一个extends工具方法,然后把很多功能划分为很多模块, 然后每个模块都作为一个单独的对象,通过extends方法将各个模块扩展进去,而不是一股脑的把模块方法挂载到jquery.prototype对象上,这样做不仅干净优雅 ,而且方便后期修改维护, 同时通过extends方法提供给我们一个扩展方法,既考虑到本身的模块化,又考虑到后期的修改和扩展
  • 享元模式,目的:减少对象数量,做法:把这些对象分析,分析出私有的数据和方法,分析出公用的数据和方法
    • 容错处理,是一种代码健壮性的体现,防止错误使用出现问题
  • 模块化支持的检测
    (function(window, undefined){
      function jQuery(selector){
        return new jQuery(selector) // 这样会造成循环调用,不对
        return new jQuery.fn.init() //正确做法,无new化构建对象
      }
      
      jQuery.prototype = {
        init: function(){
    
        }
      }
      // 享元模式
      jQuery.extends = function(){
        var target = arguments[0] || {}
        var length = arguments.length
        var i = 1
        if(target!=='object'){
          target = {}
        }
        if(length === 1){
          target = this
          i--
        }
        for(var item in arguments[i]){
          target[item] = arguments[i][item]
        }
      }
      jQuery.prototype = jQuery.prototype.init.prototype = jQuery.fn 
      // 利用js引用类型的特点,共享原型
      // 把这三个都指向jQuery.prototype对象, 这样做修改时,只需要修改jQuery.prototype对象即可,做到共享原型的效果
    
      window.jQuery = jQuery
      window.$ = jQuery
    
      // 模块化支持的检测
      if(typeof define === 'function' && define.amd && define.amd.jQuery){
        define('jquery', [], function(){ return jQuery }) //通过amd的规范把jquery暴露出来
      }
    })(window,undefined)
    
    // vue中的模块化检测
    // commonJS支持和amd支持 
    (function(global, factory){
      typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : typeof define === 'function' && define.amd ? define(factory) : (global = global || self, global.Vue = factory())
    })(this, function(){
      'use strict'
    })