ES6特性:模块化、包管理器简单使用

ES6自学文档

简介

ES6是一个泛指,含义是 5.1 版以后的 JavaScript 的下一代标准,涵盖了 ES2015、ES2016、ES2017 等,ES6 的第一个版本,在 2015 年 6 月发布了正式名称就是《ECMAScript 2015 标准》(简称 ES2015)。
ES6在ES5的基础上拓展了很多新特性

(1)JavaScript包含三部分:ECMAScript、DOM、BOM,其中ECMAScript是JavaScript的核心标准。ES6是ECMAScript的升级版本,也就是说JavaScript的核心部分进行了升级,在ES6中不包含DOM和BOM操作
(2)ECMAScript 和 JavaScript 的关系是,前者是后者的规格,后者是前者的一种实现。
(3)ES6兼容性差,需要找工具来提高兼容性。常用工具有bable-cli(转码工具),可以将ES6代码在编译时转换为ES5代码。


简单对比ES5和ES6

ES5ES6
语法比ES6稍微复杂,操作比较复杂操作简单,语法简单
兼容性好兼容性不好,需要借助转译工具
变量只有var变量有let、const
只有全局作用域,函数作用域,无块级作用域有全局、局部以及块级作用域
变量声明可以提升变量声明不可以提升
变量重复赋值会覆盖前面的值不能重复赋值
没有模块体系有模块体系

1、模块化/工程化

Javascript一直没有模块体系,无法将一个大程序拆分成互相依赖的小文件,再用简单的方法拼装起来。这对开发大型的、复杂的项目形成了巨大障碍。
在 ES6 之前,社区制定了一些模块加载方案,最主要的有 CommonJS 和 AMD 两种。前者用于服务器,后者用于浏览器。
而ES6 在语言标准的层面上,实现了模块功能,而且实现得相当简单,完全可以取代 CommonJS 和 AMD 规范,成为浏览器和服务器通用的模块解决方案。
一个模块就是一个独立的文件。该文件内部的所有变量,外部无法获取。

从 v13.2 版本开始,Node.js 已经默认打开了 ES6 模块支持。在v12的版本里面,需要在package.json配置文件中设置"type": "module",

  • 简单介绍下其他模块化规范及其模块化规范产品
    1、CommonJS,使用该规范的有NodeJS、Browserify,处理浏览器的。
    2、AMD,使用该规范的有requireJS,处理服务器的。
    3、CMD,使用该规范的有seaJS

1.1 ES6模块化*

如果学过java,可以把模块化看成是java中的导包打包的操作,使用到的关键字也很相似,例如导出模块export,导入模块import。

1.1.1 简介

ES6 模块的设计思想是尽量的静态化,使得编译时就能确定模块的依赖关系,以及输入和输出的变量。
ES6 模块不是对象,而是通过export命令显式指定输出的代码,再通过import命令输入。引入模块其实就是加载模块里面的方法或者变量,这个加载过程称为“编译时加载”或者静态加载,即 ES6 可以在编译时就完成模块加载,而CommonJS模块是运行时加载,ES6要比 CommonJS 模块的加载效率高。
ES6 的模块自动采用严格模式,即严格按照语法来。

1.1.2 export导出模块

1.1.2.1 介绍

如果希望外部能够读取模块内部的某个变量,就必须使用export关键字输出该变量。export命令规定的是对外的接口,必须与模块内部的变量建立一一对应关系,也就是说外部接口需要用这个接口名来引用。
例如:在src目录下创建一个testModal.js文件,文件内容如下:

let firstName = "Michael";
let lastName = "vichy";
export {firstName, lastName};
  • 使用ES6的要求
    首先必须在package.json配置文件添加如下内容"type": "module",不添加会报错,例如在终端执行如下:
    在这里插入图片描述
    在package.json配置文件中添加如下内容才能正常运行
    在这里插入图片描述
    添加后的运行结果
    在这里插入图片描述
1.1.2.2 export的使用方式
let firstName = "Michael";
let lastName = "vichy";

//列表形式导出
export {firstName, lastName};

//重命名变量后导出,使用AS进行重命名
export {firstName as first, lastName as last};

//导出单个属性
export let a = 3;
//下面这样的形式是错误的
let b = 1;
export b;  //报错
// 这里报错的地方要么改成
// export {b}; //写成列表形式
// 要么改成
// export let b = 1;

//导出一个函数
export function multiply(x,y){
    return x * y;
}

//默认导出
/*注意:
一个模块只能有一个默认导出
*/
export default {} //第一个默认导出
// export default function foo(){} //第二个默认导出,报错,只能有一个默认导出。

//导出整个文件


需要特别注意的是,export命令规定的是对外的接口,必须与模块内部的变量建立一一对应关系,不能直接导出一个值。

1.1.3 import导入模块

1.1.3.1 介绍

静态的import 语句用于导入由另一个模块导出的绑定。
使用import命令的时候,用户需要知道所要加载的变量名或函数名,否则无法加载.
而有时候这需要查文档。有时候确实有人不想查看文档去了解变量名等,懒人是促进发明创新的先锋,为了给用户提供方便,让他们不用阅读文档就能加载模块,就要用到export default命令,为模块指定默认输出。
例如:

export default function foo() { 
	console.log('foo'); 
}

其他模块加载该模块时,import命令可以为该匿名函数指定任意名字。如下:

import customName from './export-default'; 
customName(); // 'foo’
1.1.3.2 import的使用方式
// 导入整个模块内容
import * as person from '要导入模块的路径'
	
// 导入列表内的多个接口
import {firstName,lastName} from '要导入模块的路径'

// 重命名导入
import {firstName as name} from '.要导入模块的路径'	

// 运行整个模块而不导入任何值
import '要导入模块的路径';

// 导入使用export default导出的模块,myDefault是给匿名函数(默认函数)任意指定的名字
import myDefault from '要导入模块的路径';  
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <script type="module">
        import * as s1 from "../JS/test10.js";
        console.log(s1);
    </script>
</body>
 </html>

// test10.js文件 // 导出 export let school = "qinghua";
 export function teach(){
    console.log("环境加入!"); 
 } 

这里是引用

1.2 CJS模块化

1.2.1 介绍

CommonJS (CJS) 和 AMD 模块,都只能在运行时确定模块之间的依赖关系,以及输入输出的变量。比如,CommonJS 模块就是对象,输入时必须查找对象属性。

例如如下代码:

// CommonJS模块 
let { stat, exists, readfile } = require('fs');
// 等同于如下代码块
let _fs = require('fs'); 
let stat = _fs.stat;
let exists = _fs.exists; 
let readfile = _fs.readfile; 

上面代码的实质是整体加载fs模块(即加载fs的所有方法),生成一个对象(_fs),然后再从这个对象上面读取 3 个方法。这种加载称为“运行时加载”,因为只有运行时才能得到这个对象,导致完全没办法在编译时做“静态优化”。

1.2.2 模块对象

Node内部提供一个Module构建函数。所有模块都是Module的实例。每个模块内部,都有一个module对象,代表当前模块。它有以下属性,通过module.XXX来使用:

属性说明
id模块的识别符,通常是带有绝对路径的模块文件名
filename模块的文件名,带有绝对路径
loaded返回一个布尔值,表示模块是否已经完成加载
parent返回一个对象,表示调用该模块的模块
children返回一个数组,表示该模块要用到的其他模块
exports表示模块对外输出的值

1.2.3 exports导出

为了方便,Node为每个模块提供一个exports变量,指向module.exports。使用module.exports={}或者exports.XXXX=""来导出。
同在每个模块头部,有一行这样的命令:

let exports = module.exports;

1.2.4 require导入

require函数是nodejs提供的内置函数,用于加载指定路径的模块或者是指定名称的模块。将加载的模块进行返回,使用如下:

let path = require('指定模块路径\名称');

1.2.5 CJS导出导入的具体使用

src下创建testExports.jstestRequire.js文件,testExports.js用来测试导出,testRequire.js用来测试导入。

testExports.js文件内容如下:

// 导出
module.exports = {
  firstName: 'Michael',
  lastName: 'vicky'
  say:function(){
	console.log(firstName + " " + lastName);
	}
};

testRequire.js文件内容如下:

// 导入
const { firstName, lastName, say } = require('./testExports');
console.log(firstName, lastName);
say();

执行node src/testRequire.js命令,能正常输出结果。

1.3 使用模块化的好处

1、防止命名冲突

  1. JS本身是没有命名空间的,为了减少命名冲突,经常使用对象或者闭包来减少命名冲突。对象只能减少命名冲突的概率,闭包的过多使用会造成内存泄漏。模块化开发之后,在模块内任何形式的命名都不会和其他模块的命名产生冲突,有效的解决了命名冲突的问题。
    2、实现代码复用
    当我们想要实现某个功能的时候,如果某个模块正好有这个功能,我们就可以直接引用该模块,不必再写多余的代码,这样可以提高代码整体的效率,减少重复冗余的代码。
    3、高维护性
    4、解决文件之间的高度依赖
    当你引入很多个JS文件的时候,很有可能会不清楚这些JS文件之间的依赖关系,从而导致加载顺序出错。使用模块化开发之后就能避免这个问题。

1.5 ES6和CommonJS模块化的区别

  • ES6 模块输出的是值的引用。
    ES6 模块加载的不是对象,它的对外接口只是一种静态定义,在代码静态解析阶段就会生成。ES6 模块输出的是值的引用
  • CommonJS 模块输出的是一个值的拷贝。
    CommonJS加载的是一个对象,即module.exports属性,该对象只有在脚本运行完才能生成。CommonJS 模块输出的是值的拷贝。
  • CommonJS 模块是运行时加载,ES6 模块是编译时输出接口。

验证ES6导出的是值引用,如下:

//testES6.js
let firstname = 'ren';
let lastname = 'terry';
setTimeout(() => {
  firstname = 'zhao';
}, 2000);
export { firstname, lastname };

//===============另一个文件===============
//useES6.js
import { firstname, lastname } from './testES6.js'
console.log(firstname, lastname);
setTimeout(() => {
  console.log(firstname, lastname);
}, 4000);

结果:

$ node src/useES6.js
ren terry
zhao terry

验证CommonJS导出的是值的拷贝,如下:

//testCommonJS.js
let firstname = 'ren';
let lastname = 'terry';
//设置任务队列,在主线程执行之后再执行,虽然这里放在导出的前面,因为导出是主线程的操作,所以其实会先进行主线程中的导出操作,之后再执行这个任务队列。并且在主线程输出值了之后,即便模块内部进行重新赋值也改变不了结果。
setTimeout(() => {
  firstname = 'zhao';
}, 2000);
module.exports = {
  firstname: firstname,
  lastname: lastname
  // 对象属性的简写方式
  /* firstname,
  lastname */
};

//===============另一个文件===============v
//useCommonJS.js
let { firstname, lastname } = require('./testCommonJS.js');
console.log(firstname, lastname);
setTimeout(() => {
  console.log(firstname, lastname);
}, 4000)

结果:

$ node src/useCommonJS.js 
ren terry
ren terry

2、包管理器

NPM 是 Node.js 标准的软件包管理器。在 2017 年 1 月时,npm 仓库中就已有超过 350000 个软件包,这使其成为世界上最大的单一语言代码仓库,并且可以确定几乎有可用于一切的软件包。它起初是作为下载和管理 Node.js 包依赖的方式,但其现在也已成为前端 JavaScript 中使用的工具。
npm工具在安装了nodejs软件后就安装好了。所以如果没有安装nodejs软件,需要先安装nodejs软件。

中使用的工具。

NPM是Javascript开发者能够更方便的分享和复用以及更新代码的工具,被复用的代码被称为包或者模块,一个模块中包含了一到多个js文件。在模块中一般还会包含一个package.json的文件,该文件中包含了该模块的配置信息。该文件是个json文件,其配置信息如下:
name 模块名称
version 模块版本
description 描述信息
main 指定模块入口文件
type 当type值为module的时候,支持es模块化
scripts 脚本,使用’ npm run 脚本名’可以调用
dependencies 依赖关系
devDependencies 环境依赖或测试依赖

常用的有三类包管理器,并且这几个包管理器可以互相替换。cnpm 是 npm 的一个替代选择,yarn 也是 npm 的一个替代选择。

通常npm的下载安装速度是很慢的,有如下几种方式可以提高下载安装速度。

  • 方案一:修改npm仓库地址为淘宝仓库地址

    # 修改npm下载的仓库地址
    $ npm config set registry http://registry.npm.taobao.org/
    # 改回原来的地址
    $ npm config set registry https://registry.npmjs.org/
    # 查看是否修改成功
    $ npm config get registry
    
  • 方案二:可以使用淘宝的npm镜像cnpm,cnpm的使用与npm使用非常类似。不过在使用之前要先安装cnpm。

$ npm install -g cnpm --registry=https://registry.npm.taobao.org
  • 方案三:可以使用淘宝yarn工具,yarn的使用与npm使用类似。不过在使用之前要先安装yarn。
$ npm install -g yarn --registry=https://registry.npm.taobao.org
MAC下下载可能会提示错误,一般是提升权限问题,命令前加个su

修改npm权限
执行npm的时候有时会遇到权限不足的情况,可以通过以下方式进行修正。

$ npm config get prefix
$ sudo chown -R $(whoami) $(npm config get prefix)/{lib/node_modules,bin,share}

2.1 npm包管理器

通过npm可以为当前项目安装依赖模块,更新依赖模块,删除依赖模块。

  • 创建一个app目录,终端进入到该app目录,使用如下命令初始化项目,会在项目根目录下会创建packge.json文件。
# 以下命令会一步一步创建项目
$ npm init
# 以下命令会快速创建项目
$ npm init -y

重新安装npm命令,使用以下命令来更新npm
npm install npm@latest -g

  • 安装单个模块依赖
# 不带-g的为本地安装
$ npm install <module_name>
# 如下命令带-g是全局下载依赖
$ npm install -g <module_name>
$ npm install --global <module_name>
# 如下命令会在项目内下载依赖,并将安装记录保存在package.json的dependencies内,安装产品阶段的依赖
$ npm install -S <module_name>
$ npm install --save <module_name>
# 如下命令会在项目内下载依赖,并将安装记录保存在package.json的devDependencies内,安装生产阶段的依赖
$ npm install -D <module_name>
$ npm install --save-dev <module_name>
  • 安装项目全部依赖模块

    $ npm install
    
  • 更新依赖模块

    $ npm update <module_name>
    
  • 删除依赖模块

    $ npm uninstall <module_name>
    

全局安装,安装到全局,在任何目录下都可以使用你安装的这个插件;
项目安装,安装到当前项目的文件夹内,只能在项目目录内使用。
项目开发思想:工具全局安装,项目依赖局部安装
无论在哪个目录下执行安装代码cnpm install -g 包名,都是全局安装。

//============================================================================
A)npm install本地安装:
(1)将安装包放在 ./node_modules 下(运行 npm 命令时所在的目录),如果没有 node_modules目录,会在当前执行 npm 命令的目录下生成 node_modules 目录。
(2)可以通过 require() 来引入本地安装的包。

B)npm install -g全局安装:
(1) 将安装包放在 /usr/local 下或者你 node 的安装目录。
(2)可以直接在命令行里使用。

//============================================================================
A)npm install --save
(1)会把msbuild包安装到node_modules目录中
(2)会在package.json的dependencies属性下添加msbuild
(3)之后运行npm install命令时,会自动安装msbuild到node_modules目录中
(4)之后运行npm install --production或者注明NODE_ENV变量值为production时,会自动安装msbuild到node_modules目录中

B)npm install --save-dev
(1)会把msbuild包安装到node_modules目录中
(2)会在package.json的devDependencies属性下添加msbuild
(3)之后运行npm install命令时,会自动安装msbuild到node_modules目录中
(4)之后运行npm install --production或者注明NODE_ENV变量值为production时,不会自动安装msbuild到node_modules目录中

2.2 cnpm包管理器

使用方式和npm包管理器一致。

  • 全局安装cnpm

    $ npm install -g cnpm --registry=https://registry.npm.taobao.org
    
  • 测试是否安装成功

    $ cnpm -v
    
    • 初始化项目,在项目根目录下会创建packge.json文件
    # 以下命令会一步一步创建项目,会让用户输入一些项目信息,参考之前package.json里的信息
    $ cnpm init
    # 以下命令会快速创建项目
    $ cnpm init -y
    
  • 安装单个模块依赖

    $ cnpm install <module_name>
    # 如下命令全局下载依赖
    $ cnpm install -g <module_name>
    $ cnpm install --global <module_name>
    # 如下命令会在项目内下载依赖,并将安装记录保存在package.json的dependencies内,安装生产阶段的依赖
    $ cnpm install -S <module_name>
    $ cnpm install --save <module_name>
    # 如下命令会在项目内下载依赖,并将安装记录保存在package.json的devDependencies内,安装产品阶段的依赖
    $ cnpm install -D <module_name>
    $ cnpm install --save-dev <module_name>
    
  • 安装项目全部依赖模块

    $ cnpm install
    
  • 更新依赖模块

    $ cnpm update <module_name>
    
  • 删除依赖模块

    $ cnpm uninstall <module_name>
    

2.3 yarn包管理器

yarn包管理器与npm类似,作用相同,命令有所不同。

yarn中文文档

  • 全局安装yarn

    $ npm install -g yarn --registry=https://registry.npm.taobao.org
    
  • 测试是否安装成功

    $ yarn -v
    
    • 初始化项目,在项目根目录下会创建packge.json文件
    # 以下命令会一步一步创建项目
    $ yarn init
    # 以下命令会快速创建项目
    $ yarn init -y
    
  • 安装单个模块依赖

    # 如下命令会在项目内下载依赖,并将安装记录保存在package.json的dependencies内,安装生产阶段的依赖
    $ yarn add <module_name>
    # 如下命令会在项目内下载依赖,并将安装记录保存在package.json的devDependencies内,安装产品阶段的依赖
    $ yarn add <module_name> --dev
    
  • 安装项目全部依赖模块

    $ yarn
    
  • 更新依赖模块

    $ yarn upgrade <module_name>
    
  • 删除依赖模块

    $ yarn remove <module_name>
    

2.4 包管理器对比

用途npmcnpmyarn
初始化项目npm initcnpm inityarn init
安装项目的所有依赖npm installcnpm installyarn
安装xxx依赖到产品阶段npm install xxx --savecnpm install xxx --saveyarn add xxx
安装xxx依赖到开发阶段npm install xxx --save-devcnpm install xxx --save-devyarn add xxx --dev
移除xxx依赖npm uninstall xxx --savecnpm uninstall xxx --saveyarn remove xxx
更新项目依赖包npm update --savecnpm update --saveyarn upgrade
  • 2
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值