2020-03-09 分析源码学架构--那些源码教我的事

PPT的开始

1

一、如何分析源码:

分析源码

源码能给我们带来什么?
优秀的架构设计思维:

注意框架设计思维,如vue响应式的思维,如何设计,如何模仿搭建架构。

对于所用工具更深的理解

通过阅读源码,对工具理解更深,帮助我们更好的使用工具。

优秀的技巧

通过看源码,学习优秀的技巧,优秀的框架,代码的质量必然很高,掌握别人如何去写的,哪里写得好。

二、源码都有的特性

开始时会出现大量的健壮的处理:if else 的判断,阅读时大部分可以忽略掉。

健壮事例:
//不够健壮的代码
function add(a,b){
    return a+b;
}
function add(a,b){
    if(! typeof a == 'number'){
      a =0;
    }
    return a+b;
}
//健壮性最有效的保证就是在参数层面去判断
健壮性事例:

Node中读取文件,但是文件可能不存在,如果不处理,可能就会报错,Node是服务,那么一定是持久的,如果不加判断,可能这个异常会导致服务的停止。那么我们如何去增强其健壮性?

try{//把容易出问题的代码用 try 包裹起来
  fs.readFile('xxx');
}catch(e){
  console.log(e);
}

其他源码的事例:


多判断
读源码规则:

源码往往是模块调用模块
不要试图一句一句的读源码
先理架构,在看入口,按流程读下去
摒弃其他代码,寻找核心代码

经典框架都是什么样的套路

分别有工厂模式,建造者模式,函数式;

(1)工厂模式 ----> 给一个批量对象的工厂,来帮助你获取对象
应用场景:你的框架,插件,需要大量的产出对象时
举例:jquery
如果每一次使用的话 都用new $()是不是特别繁琐,所以 jquery没有new,而是使用$. 或者$('xxx'). 的形式
举例:弹窗插件
页面中也会经常用到,如果每次都去new PopWindow()也是很繁琐的,最好的使用方式就是通过PopWindow.Show()的方式。

(2)建造者模式 ----> 构造比较复杂,产生的东西不多,一个页面只有一个的情况下
例如:好比建造房子,不可能从头到尾原材料加工,而是钢筋,砖瓦一起拼接到一起的来建造房子的。

举例:

function banner(){
  this.htmlInit = new htmlInit();
  this.runner = new runner();
} 
function htmlInit(){}
function runner(){}

举例:
vue 利用的建造者模式

函数式编程:
loadsh,都是函数式编程。

疑问:为什么VUE3 又变回函数式?
(1)、组合大于继承,
优点:组合扩展性更好,继承的话 还要修改其他父类子类。
缺点:需要再次调用,重复写方法的名字。
!!! 重要:能用组合的不要用继承来解决。

function a(){}
function b(){}
function c(){
  a();
  b();
}

(2)、为了使用tree-shaking库
如果这个库有100个方法,但是你只用到2个方法,那么用tree-shaking,他只会帮你把这两个方法打包进去。
但是tree-shaking只会对函数有效,无法对对象进行操作shaking。

(3)、压缩的时候,独立的方法压缩的更简单
如:

function add(){}
压缩成
_a(){}

三、手写jQuery。

(function(window){
  function jquery(seletor){
    return new jquery.fn.init(seletor);
  }
  jquery.fn.init.prototype=jquery.fn;
  jquery.fn = jquery.prototype={
    init:function(){

    }
  }
  jquery.extend = jquery.fn.extend = function(){
    //前提:这个方法可能会传1个参数,也可能传两个,如何优化?
    //不规范的写法
    if(arguments.lenght == 1){
      for(var item in arguments[0]){
        this[item] = arguments[0][item]//{a:1}  ==> a = 1
      }
    }else{
       for(var item in arguments[1]){
        arguments[0][item] = arguments[1][item]
      }
    }

    //规范写法:享元模式的写法:拿出不同的,保留相同的。
    var target = arguments[0]||{};
    var options;
    var i = 1;
    if(arguments.length == 1){
      target = this;
      i--;
    }
    options = arguments[i];//如果只有1个,那么i0,这时候拿的是第一个参数

     for(var name in options){
        target[name] = options[name]
    }
  }

  jquery.fn.extend({
      //CSS 模块会扩展在这里面
  })
  
 jquery.fn.extend({
      //动画模块扩展
  })

//模块化检测的,插件,模块,建议大家都去加入这个判断 amd ,cmd;
  if(typeof define === "function" && define.amd && define.amd.jQuery) {
      define( "jquery",[],function(){ return jQuery });
  }

  window.jquery = window.$=jquery;
})(window)

疑问:为什么jquery每个方法都需要传递window?

答案:是因为减少查找,提高性能,javaScript查找window对象的时候,会先从当前层级一步步往外查询,如果发现当前层级有window,那么就可以直接使用,如果没有继续向上一层查找,直到找到最外层window为止。
我们这儿window传进来,则不会去向外查找,解决性能上的优化,减少查找时间。

vue 源码初始化的模块化的判断
(function (global,factory){
  typeof exports === 'object' && typeof module !== 'undefined' 
          ?
           module.exports = factory()
           :
           type define === 'function' && define.amd 
                ?
                 define(factory) 
                 : 
                 (global = global || self,global.Vue = factory());
}(
  this.,function(){
    .....
  }  
))

检测当前使用的是什么规范,再使用当前有的规范去初始化

四、Express 部分源码

举例,如果app对象上面有很多方法,应该怎么写最简洁

const http = require('http');
var app = module.exports={}
app.handle = function(req,res){
  res.end('hello');
}
//错误写法
app.post = {

}
app.get = {

}
app.put = {

}
......

//靠谱点的写法 ,用桥接模式
var methods=['put','get','post','delete'];
methods.forEach((method)=>{
  app[method]=function(){
    router[method].call(this);//在通过路由去分发他们要做的事情
  }
})

你可能感兴趣的:(2020-03-09 分析源码学架构--那些源码教我的事)