复习:ES6 变量let、箭头function、参数等、map、reduce、filter、forEach Promise消除回调,Promise.all([p1,p2,p3]).then() 单独Promise并不能帮我们解决所有问题,还有2个兄弟是从Promise过度出来的,generator ,async* generator ,async* 严格来说是属于ES7的东西
//generator怎么去用,先抛弃不要想Promise generator 翻译:生成器 generator -- 特殊的函数 普通函数 --》 【开始执行,一路到底】 ---》飞机(没法停) generator 函数 --》 【中间能停】 , 踹一脚走一步 --》出租车(随时可停) //普通函数-无法中间停 <script> function show(){ alert('a'); //想中间停 alert('b'); } show(); </script> //中间可以停 <script> function *show(){ //generator特点:星号* alert('a'); yield; //告诉在哪停 alert('b'); } let obj = show(); //执行完并不会执行函数代码,会生成generator对象 obj.next(); //简单理解踹一下走一下,走到第一个yield停住,//alert:a obj.next();//alert:b </script>
yield可以: 1、传参 2、有返回值【可以阶段性传参】 作用:类似炒菜过程
<script> function *show(){ alert('a'); yield 12; alert('b'); return 5; } let obj=show(); let res1=obj.next(); //{value: 12, done: false} //done有没有完成 console.log(res1); let res2=obj.next(); //{value: 5, done: true} console.log(res2); </script> //传参 <script> function *show(a,b){ alert('a'); console.log(a,b); let c=yield; console.log(c); alert('b'); return 5; } let obj=show(12, 5); let res1=obj.next();//undefine 第一次next没有结果【下图理解】 let res2=obj.next(888); </script>
为什么好好函数?中间需要停一下?,例如:生活打车为什么中间要停一下【接人,忘了东西】
程序中为啥要停一下,等待某些操作结束,例如:数据交互。
function *show(){ xxx xxx let data1 = yield $.ajax('a.text') xxx xxx let data2 = yield $.ajax('b.text') xxx xxx } 比方说我有个函数,等待a请求的ajax结束,然后收集数据data1,等下下一个b的ajax请求,我们知道generator函数走到yield要暂停,next()往下执行。但是我们是否可以通过同步写法,完成异步的操作? 需要辅助工具 node小工具 安装cnpm npm install -g cnpm --registry=https://registry.npm.taobao.org cnpm search yield-runner-blue //跳出网页,搜索yield-runner-blue cnpm i yield-runner-blue //安装 install //会在当前cmd路径下,有个node_modules/yield-runner-blue 文件夹 //演示,runner封装特点:即享受到异步带来的性能优势,同时兼顾到了你写代码的习惯 <script src="runner.js" charset="utf-8"></script> <script src="jquery.js" charset="utf-8"></script> <script> //generator函数不能用箭头函数 runner(function *(){ alert('欢迎哈'); //等下数据结束,什么时候结束什么时候往下执行 let arr=yield $.ajax({url: 'data/1.txt', dataType: 'json'}); alert('接收到了数组'+arr); let json=yield $.ajax({url: 'data/2.txt', dataType: 'json'}); alert('json也读完了'); console.log(json); }); 作业1:看懂runner.js [yield-runner-blue的index.js] 作业2:搞懂传统的ajax请求和generator区别,优缺点 演示中的generator,需要依赖一个runner.js 既然generator那么好用,ES7官方也出一个runner【async/await】
既然runner.js那么好用,官方为啥不出一样
es7出了一个叫做: async / await
<script> async function show(){ alert('欢迎哈'); let arr=await $.ajax({url: 'data/1.txt', dataType: 'json'}); alert('接收到了数组'+arr); let json=await $.ajax({url: 'data/2.txt', dataType: 'json'}); alert('json也读完了'); console.log(json); } show(); //函数调用 </script> <script> //省略,箭头函数 (async ()=>{ alert('欢迎哈'); let arr=await $.ajax({url: 'data/1.txt', dataType: 'json'}); alert('接收到了数组'+arr); let json=await $.ajax({url: 'data/2.txt', dataType: 'json'}); alert('json也读完了'); console.log(json); })(); </script>
总结:
Promise本质:等待异步操作结束 generator本质:无感处理异步操作 async本质:官方runner runner(function *(){ xxx let 结果1 = yield 异步操作1 xxx let 结果2 = yield 异步操作2 xxx }); (async function(){ //可写 async ()=> xxx let 结果1 = await 异步操作1 xxx let 结果2 = await 异步操作2 xxx })()
模块【引入一个第三方登陆模块】 或等于 【元件】 或等于 【组件】 (一个东西) 1. 民间版的-sea.js , require.js CMD,和 AMD 模块的规范 *作业3: 找找CMD和AMD是什么,区别? 2. nodejs模块化 3. ES6模块化 【官方出来以后,大家抛弃了民间】
sea.js使用
bower i seajs 【官网打不开,下载一个】 模块是什么?就是一个可以重复使用单位 模块分为2个部分: 1.定义 2.调用 ----sea.js的模块使用 sea好处: 按需引用,解决依赖
//mod1.js //exports 导出 [对外导出a和b] //模块是被包起来的,需要写在define内部 define(function(require, exports, module)){ //define是有参数的 exports.a=12; exports.b=5; exports.calc=function (){ } //函数外部出口 //module作用:批量导出 module.exports={ a: 12, b: 5, show(a, b){ alert(a+b); } }; //require 用来引用其他模块 }) //直接定义是无法使用的,只能在内部,作用域 //let a=12; //let b=5;
//1.html <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title></title> <!-- 不能这么使用,不然失去模块化的意义 <script src="mod1.js" charset="utf-8"></script> --> <script src="sea.js" charset="utf-8"></script> <script> seajs.use(['mod1.js'], function (mod1){ //use引用模块 //回调函数 mod1.show(mod1.a, mod1.b); }); </script> </head> <body> </body> </html> //总结: //1.定义模块 mod1.js define(function(require,exports,module){ exports.a=12; exports.b=5; }); //2.引用模块 1.html seajs.use(['xxx.js','bbb.js'],function(mod1){}) //ES6的JSON的,key和value一样,可以简写 let a=12; let b=6; let json={a,b}; //函数可以缩写 { show:function(){} //原来写法 show(){} //新写法 }
-- mod2.js define(function (require, exports, module){ let moda=require('./a.js'); let modb=require('./b.js'); exports.res=moda.num1+modb.num2; });
-- 2.html <script src="sea.js" charset="utf-8"></script> <script> seajs.use('mod2',function (mod){ alert(mod.res); // }); </script>
seajs和require.js 本身消息了,但是这种用法还是存在的,只不是在node.js上体现 如果我是拿着html去找js,使用:use 如果在js文件里面再去找js,使用:require 在node.js里面没有use,只有require,因为都是js找js
//3.js //define() ,原来是要使用define,现在不需要了 exports.a=12; //输出a:12
//2.js exports.b=55; //输出b:55
//1.js let mod2 = require('./2');//.js可以省略,同名js使用直接使用名字:2.js = 2 let mod3 = require('./3.js'); console.log(mod2.a+mod3.b);
//seajs里面 define(function(){ let moda = require('./a'); let modb = require('./b'); //可以把.点给去掉,是一样的,可有可无 let moda = require('a'); let modb = require('b'); }); //node.js里面 let mod2 = require('2'); let mod3 = require('3.js'); //报错 //Cannot find moudle '2' //为什么: 在reajs,require.js里面只有你定义的的模块,没有别人的模块,而node.js不一样,包含有系统模块,再带的模块,http等 let http=requier('http'); //引用系统模块 console.log(http); let http2=requier('./http'); //引用自定义模块, ./表示在当前文件夹下查找http.js console.log(http2); //node_modules //想引用自己的模块,但是每次都要加【./】好麻烦,可以有一个文件夹【node_modules】,这个名字不能乱动,不能改,必须叫这个,因为默认会去这里面找东西。 let mod2 = require('2'); //这时候不带./也能出来 let mod3 = require('3.js'); console.log(mod2.a+mod3.b); //正常输出:67
node的模块化 1.没有define 2.exports,require,module 3.引用自定义模块 放到node_modules里 前面加./
--创建自己的包,发布给别人用 --node的东西习惯前面有个nmath,用于区别系统的math 1.创建文件夹 nmath 2.创建包信息 npm init --pack name(nmath) --description: this is my math package【输入描述】 --entry point: a.js 【入口文件,当别人引用你包时候,到底引用是谁】 --test command: 【你做出来东西,有相应的测试,帮你来测试的命令】 --git repository: 【托管的地址】 --keywords: math my【便于别人搜索】 --author: lisi 【作者是谁】 --license: (ISC): 【许可】 -- is this ok ? //生成package.json { "name": "nmath", "version": "0.0.1", "description": "this is my math package", "main": "a.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "keywords": [ "math", "my" ], "author": "lisi", "license": "ISC" } //a.js 入口 module.exports={ sum(a,b){ //加法 return a+b; }, divide(a,b){ //除法 return a/b; } }; 3.把你的包放到node_modules 4.使用require('nmath') //加载 //test_nmath.js const nmath=require('nmath'); //相当于require('a.js') console.log(nmath.divide(12, 66)); 5.执行测试 node test_nmath //让全世界都用上你的包, 发布你的包 6.npm publish --错误:err! code e403,verify your email 【先验证你的邮箱,先登陆】 --登陆:npm login 【会传到官网: www.npmjs.com】 --再次 npm publish
ES6模块和Node区别
ES6模块化:首先官方提供的,首先用官方的,一个性能好,一个统一标准 ES6出了2个新东西:import、export 原来民间版本不是叫:require,现在ES6官方叫:import //官方语法解释怎么用 https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/export
//1.js let a=12; //不输出是用不了的 let b=5; export{a,b} //import.html <script> import mod1 from "./1.js" alert(mod1.a); //Unexpected token import 目前浏览器还不是很支持ES6模块化 import alert(mod1.b); </script> //目前浏览器不是很支持ES6模块化,有没有什么办法? //靠工具来帮我们,ES6尽管是官方的,还是需要工具的支撑 1、ES6---目前没法浏览器用--可以用babel编译,babel可以编译普通JS代码,但是无法编译es6模块,编译模块需要WebPack 2、WabPack
//语法不同 Node: 输出 exports.a=12; module.exports={x, x, x}; 引入 let mod=require('./aaa.js'); ES6: 输出 export {x, x, x}; 引入 import mod from "./xxx.js" //加了mod可以直接用
babel不能编译模块,但是能编译ES6,可以帮助我们理解工具如何用
babel官网: https://babeljs.io/
//如何使用babel 1、.安装babel-cli cli全称:command line interface //命令行接口 build: babel src -d lib == npm run build npm i -g babel-cli //全局安装 2、在文件夹编译,创建文件夹babel_es6 //创建 1.js 文件, 大量用到es6特性 let a=12; const b=5; let arr=[{a, b}, {b, a}]; arr.sort((json1, json2)=>json1.a=json2.a); alert(arr[0].a); //1.html,在谷歌浏览器Chrome可以运行,在IE11浏览器无法运行 <html> <head> <meta charset="utf-8"> <title></title> <script src="js/1.js" charset="utf-8"></script> </head> <body> </body> </html> //2.由于IE无法运行,需要编译 //3.进入目录babel_es6 npm init //建立一个package.json,就是工程文件 //需要在scripts加一个build,目前我们暂时用不到,但是后面用到很多 "scripts": { "build": "babel js -d build" } //script用处:保存写好的命令,不用每次都打 //假如我们在命令行输入命令: node server.js --slience --no-err --report=c:/a.txt //正常启动 server.js 我需要在后面带一堆的参数,每次都要写那么多参数累死了。所以可以在 //script里面加名字,例如:serv "scripts": { "serv": "node server.js --slience --no-error --report=c:\\a.txt" } //运行的时候就可以:npm run 【npm run 这2个是固定的】 // npm run serv 【效果等同于node server.js --slience --no-error --report=c:\\a.txt】 //4.运行试试 babel js -d build //在js里面夹里面变异js文件到build文件夹 //执行后会生成build文件夹,存放处理后js文件 //报错:Error: Couldn't find preset "env" relative to directory //需要安装安装babel-preset-env,同样是在项目的根目录下通过以下命令行安装: //npm install -D babel-preset-env //5.然后运行 npm run build 或者 babel js -d build js\1.js -> build\1.js //成功后,1.js文件变成了,bulid/1.js //6.运行成功后,发现js文件内容没有什么变化,除了整齐点 //7.创建 .babelrc 配置文件 { "presets": ["env"] //presets预设,说白了babel需要大量选项需要配置,我听谁的,是你一个个给我,还 //是我默认去找一个叫做env的,说明babel有很多种模式,env就是其中一种 //安装npm install babel-preset-env --save-dev //--save-dev 就等于 -D ,开发环境依赖 //--save 是生产环境依赖 } //8.package.json 文件变化,增加了devDependencies "devDependencies": { //dev开发,devDependencies依赖: 开发模式的依赖的模块 "babel-preset-env": "^1.7.0" }
babel编译模块
文件夹结构:
/js/mod/m1.js
/js/mod/m2.js
/js/2.js
//m1.js let a=12; export {a}; //m2.js let b=12; export {b}; //2.js import m1 from "./mod/m1.js" alert(m1.a); //编译模块 npm run build //编译完后/build/2.js,内容 "use strict"; var _m = require("./mod/m1.js"); var _m2 = _interopRequireDefault(_m); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } alert(_m2.default.a); //出现了require,我们知道require原生JS无法使用。其实babel直接编译export,import作用不明显,看不到效果,还是需要搭配其他工具。
1、看yield-runner
2、看AMD和CMD的区别
3、尝试webpack编译import 和 export