现代JS的组织方式
js文件由多个模块构成,通过打包程序消除无用代码,整合到一个文件,再转换到ES5代码(BABEL),最终生成一个打包文件
NPM管理多种模块
这些步骤主要通过Webpack等打包程序进行
模块MODULE
我们可以做到引入外部模块/依赖项或导出模块
使用模块的优势:
ES6中的MODULES
一个模块一个文件,当模块被创建时,模块文件中声明的所有变量都是私有变量,因此无法被引用它的文件直接获取到
与普通js文件对比
由于js在执行开始首先对其中变量进行分析 Parsing ,此时由于模块变量被提升,他们被优先加载,然后再执行js文件
加载模块时并不是简单的复制,而是Live Connection ,模块在源文件中被同步改变。(JS独有特性)
应用
当我们引用模块文件时,在html文件中必须设置属性:
<script type="module" defer src="script.js"></script>
命名导出
直接在想要导出的变量上添加关键词export
shoppingCart.js
// Exporting module
console.log('Exporting module');
export const cart = [];
export const addToCart = function (product, quantity) {
cart.push({ product, quantity });
console.log(`${quantity} ${product} added to cart`);
};
script.js
//Importing module
import { addToCart } from './shoppingCart.js';
console.log('Importing module');
addToCart('bread', 5);
导出多个内容:
给函数起别名可以发生在导出时或导入时
const totalPrice = 237;
const totalQuantity = 23;
export { totalPrice, totalQuantity as tq };
起别名:
import { addToCart as atc } from './shoppingCart.js';
全部导入,这时导出的所有对象都被放入了as的变量中,相当于一个api:
import * as ShoppingCart from './shoppingCart.js';
ShoppingCart.addToCart('bread', 5);
默认导出
这时function变为了匿名,在导入文件时可以给他起任意名字
export default function (product, quantity) {
cart.push({ product, quantity });
console.log(`${quantity} ${product} added to cart`);
}
模块模式 Module Pattern
使用闭包将函数封装起来,示例:
这样使想要输出的函数被暴露,其他数据变为了不可访问的私有数据,类似模块的实现,因此称为模块模式
const ShoppingCart2 = (function () {
const cart = [];
const shippingCost = 10;
const totalPrice = 237;
const totalQuantity = 23;
const addToCart = function (product, quantity) {
cart.push({ product, quantity });
console.log(
`${quantity} ${product} added to cart (sipping cost is ${shippingCost})`
);
};
const orderStock = function (product, quantity) {
console.log(`${quantity} ${product} ordered from supplier`);
};
return {
addToCart,
cart,
totalPrice,
totalQuantity,
};
})();
ShoppingCart2.addToCart('apple', 4);
ShoppingCart2.addToCart('pizza', 2);
console.log(ShoppingCart2);
console.log(ShoppingCart2.shippingCost);
CommonJS Module
一种规范,不同于现在使用的npm模块系统的一种模块系统
可以在nodejs上运行但普通js文件无法编译的写法
如:
export.addTocart = function (product, quantity) {
cart.push({ product, quantity });
console.log(
`${quantity} ${product} added to cart (sipping cost is ${shippingCost})`
);
};
// Import
const { addTocart } = require('./shoppingCart.js');
NPM简单入门
- 初始化:npm init
- 安装: npm -i 或npm install 包名
- 常用库:lodash(在非nodejs环境下需要安装es版本lodash-es)
引入示例:
import cloneDeep from 'lodash-es';
const state = {
cart: [
{ product: 'bread', quantity: 5 },
{ product: 'pizza', quantity: 5 },
],
user: { loggedIn: true },
};
//浅拷贝仅拷贝了同一块地址空间,没有新建
const stateClone = Object.assign({}, state);
//深拷贝
const stateDeepClone = cloneDeep(state);
state.user.loggedIn = false;
console.log(stateClone);
console.log(stateDeepClone);
- npm package.json 使程序在拷贝时不需要移动所有包,npm会根据这个文件下载回来
Parcel的使用
- 安装 npm i parce --save-dev
- 使用npx parcel index.html 由于不是全局安装,需要使用npx,然后提供一个入口文件,打包html
- 最终打包到dist文件夹中,可交付版
- 启用热加载:
if (module.hot) {
module.hot.accept();
}
在这种情况下,可以将引入简写:
import cloneDeep from ‘lodash-es’;
无需指定具体位置,打包程序会找到
也可以直接使用import cloneDeep from 'lodash';
,打包程序将会自动识别未安装的应用,完成安装
npm脚本的使用
在package.json中,在script中写自己的脚本
{
"name": "starter",
"version": "1.0.0",
"description": "",
"main": "clean.js",
"scripts": {
"start": "parcel index.html",
"build": "parcel build index.html"
},
"author": "",
"license": "ISC",
"dependencies": {
"leaflet": "^1.9.3",
"lodash-es": "^4.17.21"
},
"devDependencies": {
"parcel": "^2.8.3"
}
}
然后cmd输入npm run start或npm run build 即可运行自定义脚本
打包程序:
最终压缩好的html
Babel
parcel自带babel转换
babel将es6的可转换的语法转为es5,而那些新增的方法,如find()并不会被转换,但是可以被polyfill
使用npm i core-js 安装
导入 import ‘core-js/stable/自己需要的方法名’;
这样可以使es6的语法按部分导入es5中,减少打包文件体积
现代代码规范
规范
声明式代码(范式)和函数式编程
命令式和声明式的区别: