PPT的开始
一、如何分析源码:
优秀的架构设计思维:
注意框架设计思维,如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);//在通过路由去分发他们要做的事情
}
})