JavaScript 模块化编程
网站越来越复杂,js代码、js文件也越来越多,会遇到什么问题?
- 命名冲突;
- 文件依赖问题。
- 解决方案:模块化开发。
什么是模块化
- 代码模块化的例子:
- 日期模块;
- 数学计算模块;
- 日志模块...
模块化开发演变
- 模块化开发思想的优点:
- 开发效率高:一次开发,多次使用;
- 维护方便:模块之间有高偶尔低内聚的特点。
- 1~4是关于命名冲突的问题,5是关于文件依赖的问题。
1. 全局函数
- 命名冲突,代码可读性差;
- 文件依赖的问题。
2. 命名空间-对象封装
- 驼峰命名;
- 用命名空间的方式进行封装(事先约定命名的规范的形式);
- 不能做到私有性封装,对象里面的属性和方法很容易被修改掉,很不安全。
3. 划分私有空间
- 通过匿名函数自执行的方法封装模块;
- 可以保护私有变量和方法。
4. 模块的维护扩展
- 开闭原则,对修改关闭,对扩展开放。
- 增加了代码的健壮性和容错性。
5. 模块的第三方依赖(文件依赖)
- 模块职责唯一性
- 把依赖的模块,通过依赖注入的形式,在你的参数上进行体现,牵强的可以解决文件依赖的问题。
总结
- 最大的问题,规范的问题
- 如果在多人协作开发过程中,会有很大的问题
- 多人协作开发过程中:代码的风格一定要统一
模块化规范
服务器端模块化规范
- CommonJS(http://www.commonjs.org/)
- Node.js(https://nodejs.org/)
浏览器端模块化规范
- AMD
- RequireJS:优先加载
- CMD
- SeaJS:懒加载
- commonjs:服务器端的规范
- node.js
SeaJS
一个基于CMD规范实现的模块化开发解决方案;
作者:Alibaba 玉伯
特性:
简单友好的模块定义规范
自然直观的代码组织方式
了解CMD规范,掌握使用SeaJS类库构建模块化开发方式。
基本使用
1.引入 sea.js 库
2.定义模块
define(function(require, exports, module){ 模块代码 });
3.依赖模块
require(‘模块id’)
4.暴露接口
exports
module.exports
5.启动模块系统
seajs.use(‘模块id’,function( 模块对象 ){ 业务代码 });
定义模块 define
- 定义模块 define(function(){})
- 函数体内的方法属性都属于这个方法,对外有封装性;解决了命名冲突问题,使js代码有了封装性;
- 直接调用 jQuery 插件等非标准模块的方法 http://my.oschina.net/briviowang/blog/208587
1.先有规范,后有实现
2.在CMD规范中,一个模块就是一个js文件
3.define 是一个全局函数,用来定义模块
4.define( factory )
对象 {} 这种方式,外部会直接获取到该对象
字符串 ‘’ 同上
函数 function( require, exports, module ){ // 模块代码 }
为了减少出错,定义函数的时候直接把这三个参数写上,而且顺序不能调换
加载模块 require
- 加载文件依赖、模块依赖的,用于define函数体内。
1.require(‘模块id路径字符串’)
用于根据一个模块id加载该模块
参数必须是一个字符串
该方法会得到 要加载的模块中的 module.exports 对象
2.只能在模块环境define中使用,define(factory)的构造方法第一个参数必须命名为 require
3.不要重命名require函数或者在任何作用域中给 require 重新赋值
暴露接口 exports 和 module.exports
- module.exports曝露出一个完整的对象,只能扔一次,只能曝露出来一个;
- exports是module.exports的别名,可以用来单个属性、方法、对象的曝露,用
.
的形式,exports能做的事情module.exports也可以做
1.功能:通过给exports或module.exports动态的挂载变量、函数或对象,外部会获取到该接口;
2.exports 等价于 module.exports;
3.可以通过多次给exports 挂载属性向外暴露;
4.不能直接给 exports 赋值;
5.如果想暴露单个变量、函数或对象可以通过直接给 module.exports 赋值 即可。
启动模块 seajs.use
- 加载入口模块,我们把define定义的js就叫模块;
- 这个用于在
html
代码里面的加载。
1.在调用 seajs 之前,必须先引入 sea.js 文件
2.通过 seajs.use() 函数可以启动模块,有三种形式
(‘模块id’[,callback] ) 加载一个模块,并执行回调函数
( [ ‘模块1’, ‘模块2’ ] [, callback] ) 加载多个模块,并执行回调函数
callback 参数是可选的
其中,回调函数中的参数用来接收通过exports返回来的值
3.seajs.use 和 DOM ready 事件没有任何关系
4.最好不要在 define 中 使用 seajs.use
其它
模块标识
- 模块标识就是一个
字符串
,用来标识模块
; - 模块标识
可以不包含后缀名 .js
; - 以
./
或../
开头的相对路径模块,相对于 require 所在模块的路径; - 不以
./
或../
开头的顶级标识,会相对于模块的基础路径解析(配置项中的base
) - 绝对路径:
http://127.0.0.1:8080/js/a.js
- 相对路径:
/js/a.js
高级配置SeaJS
属性 | 说明 |
---|---|
<span style="color:red">alias</span> | 别名配置 |
<span style="color:red">paths | 路径配置 |
vars | 变量配置 |
map | 映射配置 |
preload | 预加载项 |
debug | 调试模式 |
<span style="color:red">base | 基础路径 |
charset | 文件编码 |
requirejs
- 与seajs的区别:
- requirejs是优先加载的;
- seajs是懒加载的,就是有拖延症,用的时候才加载。
- 官方文档:http://www.requirejs.cn/
node-lesson1
1.前端、后端都是干什么的?
- 前端:做静态资源的,html、css、js、图片;
- 后端:操控服务器的硬件的。
2.为什么学习node.js?
- 1.就业有市场;
- 2.有商业用途;
国内一些创业公司用用的比较多,功夫熊(做上门保健的,美甲、按摩)
国外的一些大公司都有使用:Facebook、Twitter、Google
国内的一些大公司:Alibaba(天猫所有的页面都是通过Node提供的服务)、Tencent、Baidu - 3.本身技术是有价值;
- 4.js开发。
3.什么是JavaScript?
- 一门脚本语言,需要嵌入html执行。
4.浏览器中的JavaScript可以做什么?
- 校验表单、操作dom等等
5.浏览器中的JavaScript不可以做什么?
- 操作服务器硬件。
6.浏览器与JavaScript是什么关系?
浏览器解析js,目的是为了让计算机能看懂js(计算机看得懂01010101,机器码、字节码);
这个过程叫做编译。
实际上是内核(js引擎)去解析的:
引擎
1.转化
汽油柴油等等--->转化->成动能
模板+数据--->页面
js代码--->机器码\字节码
2.移植性
js引擎套一个壳子就是浏览器,写js代码传给js引擎,可以操作硬件,这一套技术就构成了node.js
node.js使用v8引擎去解析js(不在需要去考虑兼容性问题了)
7.JavaScript只可以运行在浏览器中吗?
- 可以运行在浏览器中;
- 也可以运行在node中(因为使用了v8引擎)。
JavaScript的实现方式
浏览器 | JavaScript实现方式 |
---|---|
Firefox | SpiderMoney |
IE | JScript |
Safari | JavaScriptCore |
Chrome | V8 |
Microsoft Edge | ChakraCore |
什么是 Node?
1.Node.js是一个在浏览器之外可以解析和执行JavaScript代码的运行时环境,或者说是一个运行时平台JavaScript是门语言,node是一门技术;
2.Node.js的特性:无阻塞IO模型、事件驱动;
3.Node.js通常用来构建提供实时服务的应用程序。
node是js运行环境基于v8引擎的一个运行时;
特点:
用事件驱动
、无阻塞的io模型
;-
优势:
轻量
、高效
。- 轻量级也就意味着 运行速度快;
- 轻量级也就意味着有更好的 跨平台 特性(平台的差异性,兼容性);
node是门技术不是语言,它使用的语言是js
java --> java
.net --> c#
node --> js
-
Node.js 是一个 构建于 谷歌 Chrome 浏览器的 V8 引擎之上的一个
JavaScript运行时
环境。- Node.js可以解析和执行 JavaScript 代码。
- Node.js的事件驱动和非阻塞IO模型使得Node.js本身非常的轻量和高效;
-
Node.js' package ecosystem, npm, is the largest ecosystem of open source libraries in the world.
- 以前的客户端中 JavaScript 库 散列在互联网的各个地方;
- npm 就是把大家经常使用的一些开源库 给组织到了一起。
Node 是一个可以解析和执行 JavaScript 代码的 运行时环境。
关于Node
1.可以在服务器端使用JavaScript了
2.统一了开发环境和语言,JavaScript无处不在
3.高性能的JavaScript引擎 – Google V8
4.诞生于2009年,由Ryan Dasl 发布,并且是开源的
5.Node.js同时支持Windows、Linux、Mac OSX
为甚嚒要学习node
全栈开发工程师
技能全面、学习能力强、沟通成本低、学习成本高;
掌握多种技能,独立完成产品。
前端开发
html、css、JavaScript、jQuery、Angular、前端优化、自动化框架等。
后端开发
Node.js构建后台服务。
移动端开发
HTML5、ionic、React native、微信等。。。
Node 的实现结构
- V8 JavaScript 解析执行引擎,ECMAScript;
- 中间层(提供了文件操作、网络操作登陆接口)更加接近操作系统的接口供开发人员使用
- 硬件层
安装与配置
3m安装法 nvm npm nrm
安装包的方式安装
- 问题1:安装了node 没有卸载;
- 问题2:32和64搞混了;
- 问题3:拼写错误,路径错误;
- 下载地址:
- 一路下一步 next
- 如何确认是否安装成功:
-
win + r
,然后输入cmd
,然后敲回车 就可以进入 cmd 控制台
-
nvm 安装和管理我们的 Node.js版本
nvm的安装方式,node.js version manager 是一个node的版本管理工具
为了解决node版本切换问题
右键在此电脑上点击一下--》属性---》系统---》高级系统设置---》环境变量
控制面板---》系统---》高级系统设置---》环境变量
NVM_HOME---C:\dev\nvm
NVM_SYMLINK--C:\dev\nodejs
新建一个path:%NVM_HOME%;%NVM_SYMLINK%
nvm | 用法 |
---|---|
nvm list | 查看版本号 |
nvm use 版本号、nvm use 版本号 32 | 用哪个版本(已经下载过的版本) |
nvm install 版本号、nvm install 版本号 32 | 下载相对应版本 |
nvm下载的是二进制版本
控制台基本使用
- 允许用户可以在终端命令台中与操作系统交互,其实就是输入与输出。
基本命令 | 说明 |
---|---|
dir |
directory列出当前目录下所有的条目,别名 ls 在 powershell 中可以使用 |
cd |
change directory 切换目录 |
mkdir、md | make directory创建一个文件夹 |
rd | remove directory删除文件夹 |
del | delete删除指定文件夹 |
ren | rename改变文件名 |
cls | clear screen清屏 |
path 环境变量
目的是为了在控制台中的任何目录都可以快速打开或者使用该可执行文件;
环境变量就是用来存储系统级别的变量;
-
添加环境变量
- 我的电脑 -> 右键选择属性 -> 高级系统设置 -> 切换到
高级
面板 -> 环境变量 - 第一种方式:直接把可执行文件所属的目录 放到 PATH 环境变量中(如果没有PATH环境变量,自己新建)
- 第二种方式:新建一个环境变量,变量名规范:逻辑名_HOME 变量值:该可执行文件所属的目录
- 注意:无论是直接添加的路径还是引用的变量名,一定要用 英文的分号 区分开
- 引用变量名的时候,变量名两边都是
%
- 我的电脑 -> 右键选择属性 -> 高级系统设置 -> 切换到
-
> feiq
:- 当你在控制台中输入一个程序的名字的时候,cmd默认把它当成一个可执行文件去执行了,优先找当前目录下是否有没有一个叫做feiq.exe的可执行文件,如果有,直接执行打开;
- 如果没有,cmd会进入 path 环境变量中一个目录一个目录的挨着查找里面是否有该可执行文件。
REPL(Read-eval-print-loop) 运行环境
- 用来测试一下代码的,repl和chrome的控制台很像;
- 通过在控制台中输入
node
敲回车就可以计入 REPL 运行环境; - 通过在REPL运行环境中,连续按两次
Ctrl+C
就可以退出 REPL 运行环境。
用node执行js文件
- 在js文件当前目录下---->node +文件名;
- 如果不在当前目录下,node + 文件路径的形式执行:
- 相对路径:
./当前路径
,../上级目录
; - 绝对路径执行js的方式:
node c:\Users\cena\Desktop\code\01helloworld.js
。
Globals
global
- global表示Node所在的全局环境,类似于浏览器的window对象;
- 使用REPL环境查看global对象;
- 注意:在REPL中定义的变量默认就是全局;
- 总结:
- global就表示Node中的全局命名空间,任何全局变量、函数或对象都是global的一个属性;
- 在一个模块中定义的变量、函数或方法只在该模块中可用,但可以通过exports对象将其传递到模块外部。
console(测试用)
断言
- 断言就是假定一个条件,如果条件成立则不输出任何内容,如果条件不成立则报错还要输出想要输出的内容。
console.assert(条件,条件不成立输出的内容);
var foo=3;
console.assert(foo==3,"失败");
time()、timeEnd()
- 成对出现,计算在两个方法中间的代码的运行时间,传入的参数要一致。
console.time('test');
//code
console.timeEnd('test');
//参数帮我们记录代码的执行时间
__dirname 和 __filename
__dirnamee
:用来找到当前文件夹的路径;;__filename
:用来去到当前文件的全路径。不知道代码要才哪使用的时候,用于灵活的写代码取路径的时候。
它们属于模块作用域,可以直接使用
它们两个用来获取路径的,一般用于操作文件路径的时候,才会用到
process
- process 是一个全局可用对象,用来和我们现在启动中的node进行交互的。
指令 | 说明 |
---|---|
process.version | 取版Node的版本,比如v0.10.18 |
process.stdout.write(123123 ) |
在控制台做标准输出 |
process.pid | 当前进程的进程号 |
process.platform | 当前系统平台,比如Linux |
process.env | 指向当前shell的环境变量,比如process.env.HOME |
process.stdout | 指向标准输出 |
process.stdin | 指向标准输入 |
process.stderr | 指向标准错误 |
fast-init
- 额外补充(装逼用),可以通过命令行,快速加载已写好的模板。
- 如需使用,请额外查文档。
补充angular知识
- 如果定义一个controller为parentController;
- 里面还有一个controller,叫selController;
- 父控制器向子控制器传值(内容),使用$scope.broadcast("事件名","内容");
- 子控制器向父控制器传内容使用$scope.emit("事件名","内容");
模块系统
node.js模块化
一个js文件在node里面我们就理解为一个模块;
require用来加载模块;(都要使用相对路径)
module.exports用来曝露属性和方法的,因为模块有封装性,需要打破封装性曝露方法和属性来;
exports是module.exports的别名,exports可以做的事情,module.exports都可以做,exports只能用.的形式曝露属性和方法。
模块的种类
- 在Node.js中,模块分为两类:
第一类,核心模块(原生模块),node自带,用`名称`直接可以加载。
核心模块:
fs:file system
异步读文件:readFile(路径,编码,function(){});
同步读文件:readFileSync(路径,编码格式);
http
os
path
querystring
url
...
第二类,文件模块,用路径加载;有一种特殊的文件模块----->包,`可以用名字加载`。
- module 是一个全局对象,它的作用是存储模块信息的,每一个js是一个模块,每一个模块里面都有一个module,module里面还存储了父子结构。可以直接给module.exports赋值,但是给exports直接赋值是无效的,用属性的形式去赋值的时候二者都有效。
2.2 优先从缓存加载
common.js规范----->加载后,再次加载时,去缓存中取 module.exports
2.3 require参数解析
核心模块是Node.js原生提供的加载核心模块的时候,
不需要传入路径,因为Node.js已经将核心模块的文件代码
编译到了二进制的可执行文件中了
在加载的过程中,原生的核心模块的优先级是是最高的
图参数解析
-
./
或../
开始的相对路径文件模块- 在加载一个自己编写的模块的时候,最好使用__dirname 和 你要加载的模块的文件名拼接。
以
/
开始的绝对路径文件模块
1.在Linux或者MAc的操作系统中,/表示系统的根路径
2.在Windows中,/表示当前文件模块所属的根磁盘路径
3.不建议使用,了解
- 标识符中可以不包含扩展名
- Node会按照
.js、.node、.json
的次序补足扩展名,依次尝试,但是不建议省略,提高效率。
require不包含扩展名的时候,Node.js会按照
路径.js 以后自己在加载js文件模块的时候,就省略掉.js后缀就可以了
路径.node 后缀为node的文件是c/c++写的一些扩展模块
路径.json 如果是加载json文件模块,最好加上后缀.json,能稍微的提高一点加载的速度
.json文件最终Node.js也是通过fs读文件的形式读取出来的,然后通过JSON.parse()转换成一个对象
Node.js会通过同步阻塞的方式看这个路径是否存在
依次尝试,直到找到为止,
如果找不到,报错
- require 加载包的时候
直接写包名,先在包内的node_modules,
目录下查找,去父级目录下的node_modules目录下查找,如果找到就直接使用;否则
依次向上查找,直到根目录。
3.包
- 还有一种特殊的文件模块,其实就是包。
- 现象:你开发的一个功能模块,还是以文件的形式散列的,你给别人使用的时候很麻烦。
- 包的作用:在模块的基础上进一步组织JavaScript代码。
3.1 包的组成
包结构:
入口文件
index.js
;-
包描述文件package.json:
name:包的名称;
description:包的简介;
version:包的版本号;
keywords:关键词数组,用于npm中分类搜索;
author:包的作者;
main:配置包的入口,默认是模块根目录下的index.js;(可以修改,main和外面的入口文件一起修改)
dependencies:包的依赖项,npm会通过该属性自动加载依赖包。
包名:“版本号”
包名:
>
+版本号 下载大于某个版本号,npm会下最新版包名:
<
+版本号 下载小于某个版本号,npm会下小于这个版本号最新版包名:
<=
小于等于 一定会下你写的这个版本,除非没有你写的这个版本包名:
>=
大于等于 下载最新版包名:
*
、" "
、X
任意 npm会给你下最新版包名:
~
+版本号 会去下约等于这个版本的最新版,在大版本不变的情况下下一个比较新的版本包名:
^
+版本号 不跃迁版本下载,^2.1.0 npm会下载大版本不变,去下载2.x.x版本里的最近版scripts:指定了运算脚本命令的npm命令行缩写,例如start。
Bin:存放可执行二进制文件的目录;
Lib:存放JavaScript代码的目录;
Doc:存放文档的目录;
Test:存放单元测试用例的代码。
其中index.js和package.json两个文件为必须文件。
package.json的创建
方法一:在当前文件夹下
npm init
,然后根据提示填内容即可。-
方二:通过fast-init(npm install -g fast-init)。
package.json
包的描述文件package.json文件内部就是一个JSON对象,该对象的每一个成员就是当前项目的一项设置,
比如name就是项目名称,version就是项目的版本号。在模块的加载机制中,有一个main属性是非常重要的,它很大意义上决定了包要导出的模块位置。
所有的包必须要放在
node_modules
文件夹下,该文件夹和要引用包的文件同级。
npm的基本使用
基于Node.js开发的包的托管网站;
Node.js包管理工具。
npm :基于包的规范实现的一个包管理工具。
npm init:初始化一个package.json文件;
npm install 包名:安装一个包
当执行npm install的时候,它会自动跑到npm的网站,然后找到该包的github地址,找到之后,下载这个压缩包,然后在执行npm install的当前目录下找一个叫做node_modules目录。如果找到,直接解压这个压缩包,到node_modules目录下;如果找不到,则新建一个node_modules目录,解压到该目录。
-
npm install -g 包名:表示全局安装
- npm在安装的时候,在全局设置了一个安装目录,只要是全局安装就会把包安装到这个目录里面去。只要是全局安装就是安装命令行工具;
npm install 缩写:npm i
当执行npm install的时候,会自动在当前目录中查找package.json文件;如果找到,找里面的 dependencies 字段,安装该字段中所有依赖的项;
-
npm docs 包名:
- 打开包相对应的文档
非常有用
;
- 打开包相对应的文档
-
npm install --save 包名: 生产环境
- 缩写:npm i -S jquery@3.*
咱们以后在做项目的时候,先初始化一个package.json文件,在安装第三方包依赖的时候,必须使用npm install --save express,添加依赖项到package.json文件中,
实际就是添加到dependencies字段中;-
npm install -save-dev 开发环境
- 缩写:npm i -D jquery@3.*
咱们以后在做项目的时候,先初始化一个package.json文件,
在安装第三方包依赖的时候,必须使用npm install --save express,添加依赖项到package.json文件中,
实际就是添加到devDependencies字段中。npm config set prefix “路径”:修改全局安装目录,不建议使用,建议去文件夹里面改 C:\Users\用户名 里面有一个 .npmrc文件,去里面改prefix = C:\dev\npm (写你的路径);去全局的环境变量path里把C:\dev\npm 路径加进去。
npm root -g:查看全局包安装路径;
npm list:查看当前目录下安装的所有包;
npm list -g:查看全局包的安装路径下所有的包;
npm uninstall 包名:卸载当前目录下某个包;
npm uninstall –g 包名:卸载全局安装路径下的某个包;
npm update 包名:更新当前目录下某个包;
npm update –g 包名:更新某个全局工具包;
npm update:更新当前目录下安装的所有包;
npm update –g:更新全局所有的工具包。
npm 这种东西的最终的目的就是:让你的开发模式工程化,都依靠工具来管理
nvm npm nrm
3m
nvm node版本的管理工具
npm node的包管理工具
nrm npm的数据源管理工具
npm install -g nrm
4.文件操作
4.1箭头函数(ES6语法)
箭头函数就是一种语法糖;
语法糖是一种语法,用这种语法能尝到甜头,能是编程高效。
当函数体有一个参数有返回值的时候
var foo=function(v){ return v;}
//改写为箭头函数
var foo=v=>v;
- 当函数体没有参数有返回值的时候
var foo=function(){ return v;}
var foo=()=>v;
- 当函数体有多个参数有返回值的时候
var foo=function(v1,v2){ return v1+v2;}
var foo=(v1,v2)=>v1+v2;
- 当函数体有多个参数没有返回值的时候
var foo=function(v1,v2){
console.log(v1); console.log(v2);
}
var foo=(v1,v2)=>{
console.log(v1); console.log(v2);
};
4.2文件读写
- fs.readFile() 读文件
fs.readFile(file, [options], callback)
//file 读文件的路径
//options 用[]包裹的可选参数,object {"encoding":"uft8","flag":"r"} string 'utf8'
//callback function callback函数里面有两个参数
//err表示错误对象,如果readFile发生错误了,在callback函数里面会回返回err,err对象里面存着错误信息
//如何读文件成功,err为null
//data就是读文件,读出来的内容。
- fs.access(path,[mode], callback) 用来判断文件是否存在
//path 判断路径是否正确(也可以判断文件)'./pic'
//mode一般不用,默认就可以了,用的话是用来判断文件是否可读可写可执行
//callback 只有一个参数err,错,文件有问题
其它
作业
2.npm 和package.json结合着连
npm init 初始化package.json
npm install 先配置package.json里的devDependencies dependencies字段
npm i -S +包名 npm install –save 不光能下载包,还能把依赖添加到package.json
npm i -D +包名 npm install –save-dev 不光能下载包,还能把依赖添加到package.json
npm docs 包名 查看包的相关文件 jquery、mongoose、http-poster
npm list 当前目录有什么包,检测node_modules里面有什么
npm install –g 包名 全局安装 cnpm、nrm
3.cnpm
4.nrm
安装目录npm install -g nrm
nrm ls 查看数据源
nrm test 测试你的网连那个npm的数据源快
nrm use 切换数据源
5.阅读参考文献 朴灵 require
阅读参考文献 package.json全字段解析
6.github自己玩玩