javascript 构建模块化开发过程解析


Posted in Javascript onSeptember 11, 2019

在使用 sea.js 、require.js 、 angular 的时候。

我们使用到 define 、 module(require) 的方式,定义模块,和依赖模块

下面给出 define 和 module 的简单实现。 其本质,就是往一个对象上面添加方法

var F = {};
F.define = function(str,fn){
  var parts = str.split(".");
  var parent = this; // parent 当前模块的父模块
  var i = len = 0;
  //如果第一个模块是模块单体对象,则移除
  if(parts[0] == "F"){
    parts = parts.slice(1);
  }
   
  //屏蔽对 define module 模块方法重写
  if(parts[0] == "define" || parts[0] == "module"){
    return ;
  }     
   
  for(len = parts.length; i < len-1; i++){
    //如果父模块中不存在当前模块
    if(typeof parent[parts[i]] === 'undefined'){
      //声明当前模块
      parent[parts[i]] = {};
    }
    //缓存下一层父模块
    parent = parent[parts[i]];
  }
   
  if(fn && parts[i]){
    //如果给定模块方法,则绑定该模块的方法,
    parent[parts[i]] = fn();
  }
  return this;
}
 
F.module = function(){
  var args = [].slice.call(arguments);//复制参数
  var fn = args.pop(); //获取回调
   
  var parts = args[0] && args[0] instanceof Array ? args[0] : args;
   
  //模块的依赖
  var modules = [];
   
  //模块的路由
  var modIDs = "";
   
  //依赖模块的索引
  var i = 0;
   
  var len = parts.length; // 依赖模块的长度
   
  var parent,j,jlen; //父级模块,模块路由层级索引,模块路由层级长度
   
  while(i < len){
    if(typeof parts[i] == "string"){
      parent = this;
      //解析路由,并且屏蔽掉 F
      modIDs = parts[i].replace(/^F\./,"").split(".");
      //遍历模块层级
      for( j = 0,jlen = modIDs.length; j < jlen; j++){
        //迭代 父模块
        parent = parent[modIDs[j]] || false;
      }
      modules.push(parent); //将模块添加到依赖列表
    }else{
      //直接将模块添加到依赖列表
      modules.push(parts[i]);
    }
    //取下一个模块
    i++;
  }
   
   
  //执行回调,将依赖的模块注入
  fn.apply(null,modules);  
} 
//定义 string 模块
F.define("string",function(){
  return {
    trim(str){
      return str.replace(/^s+|\s+$/g,"");
    }
  }
});
//定义 string 模块,的子模块 sub
F.define("string.sub",function(){
  return {
    low(str){
      return str.toLowerCase();
    }
  }
});
console.log(F);
//使用模块
F.module(["string","string.sub",document],function(str,strSub,doc){
  console.log(str,strSub,doc)
});

当然了,这里使用的,F 对象,实际应用中,应该写在闭包里面。不能让外界直接访问,于是有如下代码。

var Sea = (function(){
  var F = {};
    F.define = function(str,fn){
    var parts = str.split(".");
    var parent = this; // parent 当前模块的父模块
    var i = len = 0;
     
    //如果第一个模块是模块单体对象,则移除
    if(parts[0] == "F"){
      parts = parts.slice(1);
    }
     
    //屏蔽对 define module 模块方法重写
    if(parts[0] == "define" || parts[0] == "module"){
      return ;
    }     
     
    for(len = parts.length; i < len-1; i++){
      //如果父模块中不存在当前模块
      if(typeof parent[parts[i]] === 'undefined'){
        //声明当前模块
        parent[parts[i]] = {};
      }
      //缓存下一层父模块
      parent = parent[parts[i]];
    }
     
    if(fn && parts[i]){
      //如果给定模块方法,则绑定该模块的方法,
      parent[parts[i]] = fn();
    }
    return this;
  }
   
  F.module = function(){
    var args = [].slice.call(arguments);//复制参数
    var fn = args.pop(); //获取回调
     
    var parts = args[0] && args[0] instanceof Array ? args[0] : args;
     
    //模块的依赖
    var modules = [];
     
    //模块的路由
    var modIDs = "";
     
    //依赖模块的索引
    var i = 0;
     
    var len = parts.length; // 依赖模块的长度
     
    var parent,j,jlen; //父级模块,模块路由层级索引,模块路由层级长度
     
    while(i < len){
      if(typeof parts[i] == "string"){
        parent = this;
        //解析路由,并且屏蔽掉 F
        modIDs = parts[i].replace(/^F\./,"").split(".");
        //遍历模块层级
        for( j = 0,jlen = modIDs.length; j < jlen; j++){
          //迭代 父模块
          parent = parent[modIDs[j]] || false;
        }
        modules.push(parent); //将模块添加到依赖列表
      }else{
        //直接将模块添加到依赖列表
        modules.push(parts[i]);
      }
      //取下一个模块
      i++;
    }
     
     
    //执行回调,将依赖的模块注入
    fn.apply(null,modules);
  }
  return {
    define:function(){
      F.define.apply(F,arguments);
    },
    module:function(){
      F.module.apply(F,arguments);
    }
  }
})();
 
 
//定义 string 模块
Sea.define("string",function(){
  return {
    trim(str){
      return str.replace(/^s+|\s+$/g,"");
    }
  }
});
//定义 string 模块,的子模块 sub
Sea.define("string.sub",function(){
  return {
    low(str){
      return str.toLowerCase();
    }
  }
});
console.log(Sea);
//使用模块
Sea.module(["string","string.sub",document],function(str,strSub,doc){
  console.log(str,strSub,doc)
});

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
一个可以显示阴历的JS代码
Mar 05 Javascript
javascript 文档的编码问题解决
Mar 01 Javascript
jQuery $.get 的妙用 访问本地文本文件
Jul 12 Javascript
jquery触发a标签跳转事件示例代码
Jul 21 Javascript
jQuery实现带滚动线条导航效果的方法
Jan 30 Javascript
jquery.serialize() 函数语法及简单实例
Jul 08 Javascript
Jquery组件easyUi实现手风琴(折叠面板)示例
Aug 23 Javascript
微信小程序 http请求的session管理
Jun 07 Javascript
详解Node全局变量global模块
Sep 28 Javascript
原生js调用json方法总结
Feb 22 Javascript
JavaScript函数节流和函数去抖知识点学习
Jul 31 Javascript
vue自定义底部导航栏Tabbar的实现代码
Sep 03 Javascript
解决layer弹出层msg的文字不显示的问题
Sep 11 #Javascript
js贪心算法 钱币找零问题代码实例
Sep 11 #Javascript
解决layui使用layui-icon出现默认图标的问题
Sep 11 #Javascript
js图数据结构处理 迪杰斯特拉算法代码实例
Sep 11 #Javascript
js简单的分页器插件代码实例
Sep 11 #Javascript
解决在layer.open中使用时间控件laydate失败的问题
Sep 11 #Javascript
关于ckeditor在bootstrap中modal中弹框无法输入的解决方法
Sep 11 #Javascript
You might like
PHP实现获取并生成数据库字典的方法
2016/05/04 PHP
laravel 实现根据字段不同值做不同查询
2019/10/23 PHP
在Javascript中定义对象类别
2006/12/22 Javascript
jquery 查找iframe父级页面元素的实现代码
2011/08/28 Javascript
更换select下拉菜单背景样式的实现代码
2011/12/20 Javascript
中文字符串截取的js函数代码
2013/04/17 Javascript
详解JavaScript基于面向对象之继承
2015/12/13 Javascript
JS实现的倒计时效果实例(2则实例)
2015/12/23 Javascript
Javascript如何判断数据类型和数组类型
2016/06/22 Javascript
JavaScript职责链模式概述
2016/09/17 Javascript
jQuery实现导航滚动到指定内容效果完整实例【附demo源码下载】
2016/09/20 Javascript
详解React-Todos入门例子
2016/11/08 Javascript
详解在AngularJS的controller外部直接获取$scope
2017/06/02 Javascript
JS实现模糊查询带下拉匹配效果
2018/06/21 Javascript
JS实现从对象获取对象中单个键值的方法示例
2019/06/05 Javascript
jquery+css3实现的经典弹出层效果示例
2020/05/16 jQuery
VUE 项目在IE11白屏报错 SCRIPT1002: 语法错误的解决
2020/09/27 Javascript
python正则表达式判断字符串是否是全部小写示例
2013/12/25 Python
Google开源的Python格式化工具YAPF的安装和使用教程
2016/05/31 Python
python设计模式大全
2016/06/27 Python
python简单图片操作:打开\显示\保存图像方法介绍
2017/11/23 Python
Python使用django框架实现多人在线匿名聊天的小程序
2017/11/29 Python
python中的文件打开与关闭操作命令介绍
2018/04/26 Python
Python 删除连续出现的指定字符的实例
2018/06/29 Python
对python模块中多个类的用法详解
2019/01/10 Python
python实现大转盘抽奖效果
2019/01/22 Python
基于python的socket实现单机五子棋到双人对战
2020/03/24 Python
TensorFlow实现简单的CNN的方法
2019/07/18 Python
Python为何不支持switch语句原理详解
2020/10/21 Python
详解pandas中利用DataFrame对象的.loc[]、.iloc[]方法抽取数据
2020/12/13 Python
授权委托书
2014/07/31 职场文书
2014年市场部工作总结
2014/11/25 职场文书
2015年英语教学工作总结
2015/05/25 职场文书
幼儿园老师新年寄语
2015/08/17 职场文书
2016年父亲节寄语
2015/12/04 职场文书
golang switch语句的灵活写法介绍
2021/05/06 Golang