🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
### ES6模块化如何使用,开发环境如何打包 * 模块化的基本语法 * 开发环境配置 * 关于js众多模块化标准 #### 语法 ~~~ export default { a:100 } ~~~ ~~~ export function fn1(){ alert() } export function fn2(){ alert() } ~~~ ~~~ import util1 from "./util1.js"; import{fn1,fn2} from "./util2.js" console.log(util1); fn1();fn2(); ~~~ export default :只默认输出一个 export好几个:{}(大括号引用) ### 开发环境babel ES6中的新语法,用到浏览器中,**需要一个编译的过程**,因为ES6的新语法在**浏览器中没有一个全面的支持**,因此开发环境中要在浏览器中使用的话要有一个转换的过程,将**新语法转化成旧版本标准的语法**,因此用到**babel** babel:js编译器(转换器) * 电脑有node环境,运行npm init * **npm install --save-dev babel-core babel-preset-es2015 babel-preset-latest** 淘宝镜像--registry=https://registry.npm.taobao.org * 创建`.babelrc`文件(.表示隐藏文件) ~~~ { "presets":['es2015','latest'], "plugins":[] } ~~~ * npm install --global babel-cli 全局安装 babel-cli(管理员模式打开) * babel --version(可以使用babel命令) * 创建./src/index * 箭头函数(ES6) * 运行**babel src/index.js** ### 开发环境 webpack babel可以将ES6语法解析成es5语法,语法层面 但针对模块化,(相互引用关系,多层次引用关系),babel不行 webpack:**可进行模块化处理**,但webpack不只是用来模块化 * npm install --save-dev webpack babel-loader * 配置webpack.config.js 新建webpack.config.js文件 (webpack是nodejs实现的,符合commonJS规范) ~~~ module.exports = { //入口文件 entry:‘./src/indx.js’, //出口配置 output:{ //当前目录 path:__dirname, filename:'./build/bundle.js'//会自动创建 }, //定义的一些模块 module:{ //定义规则 rules:[{ //所有的js除了node-modules,通过babel-loader编译 test:/\.js?$/,//.js结尾 exclude:/(node_modules)/,//除了这个目录(第三方代码), loader:'babel-loader' }] } } ~~~ * 配置package.json中的scripts ~~~ “scripts”:{ "start": "webpack", "test":''" } ~~~ * 运行npm start 其实就是运行webpack,对js代码用babel进行编译,生成到bundle.js中 ### 开发环境 rollup 相比于webpack,**更高级** **vue,react都是用rollup打包** rollup非常小,尽量简化打包后输出文件的大小 对于庞大的环境,可更优化 1. npm init 2. npm i --save-dev rollup rollup-plugin-node-resolve rollup-plugin-babel babel-plugin-external-helpers babel-preset-latest babel-core 3. 配置 .babelrc ~~~ { "presets":[ ["latest",{"modules":false}] ], "plugins":["external-helpers"] } ~~~ 4. 配置rollup.config.js ~~~ import babel from 'rollup-plugin-babel'; import resolve from "rollup-plugin-node-resolve" export default{ entry:'src/index.js', format:'umd',//格式umd即兼容页面引入script,又兼容amd,commonjs plugins:[ resolve(), babel({ exclude:'node_modules/**' }) ], dest:'build/bundle.js' } ~~~ 5. 修改package.json的scripts ~~~ "scripts":{ "start":'rollup -c rollup.config.js' "test":'' } ~~~ 6. 运行npm start webpack打包127行,rollup打包30多行 roll up:打包之后代码基本不会改,你的还是你的,不会有太多冗余代码 * **rollup功能单一**(打包模块化),**webpack功能强大**(学习成本高) * 参考设计原则,**单一值原则**(做成一个单一功能就行,没必要更好,更快,更强,更全面,最好一个东西只做一件,做好就行)(越简单越好,不用功能全面) * **工具要尽量功能单一,可继承,可扩展** * wangEditor用的gulp+rollup(开源工具) ### 关于js众多模块化标准 1. 没有模块化 2. **AMD成为标准**,require.js(也有CMD,但用的比较少) require,define这些语法定义,**完成模块化的编写**,AMD成为标准, 完善的前端工程体系 **前端需要掌握AMD标准** 3. 前端打包工具,使得nodejs模块化可以被使用 gulp,webpack(commonJS模块化可以被使用,commonJS是后端标准,通过后端打包工具打包成前端可识别的方式) 4. ES6出现,想统一现在所有模块化标准 5. nodejs积极支持,浏览器尚未统一(服务端可以使用) 浏览器不敢把es6放开用,因为比较危险,在服务端用es6写没有问题,但浏览器端需要通过工具把es6打包成es5 6. 你可以自造lib,但不要自造标准 ### 问题解答 1. 语法:import export (注意有无default) 2. 环境:babel编译ES6语法的核心工具,模块化可用webpack和rollup 3. 扩展:模块化统一的期望 ***** ### Class和普通构造函数有何区别 1. js构造函数 2. Class基本语法 3. 语法糖 4. 继承 react ~~~ class Ad extend React Component{ constructor(props){ super(props); this.state={ data:[] } }, render(){ return( <div>hello imooc</div>) }, componentDidMount(){} } ~~~ 1. js构造函数 ~~~ //构造函数 function MathHandle(x,y){ this.x = x; this.y = y; } //原型 MathHandle.prototype.add = function(){ return this.x+this.y } //实例 var m = new MathHandle(1,2); console.log(m.add()); typeof MathHandle //"function" MathHandle === MathHandle.prototype.constructor;//true m.__proto__=== MathHandle.prototype//true ~~~ 2. Class基本语法 更加统一化 ~~~ //名字后直接大括号 class MathHandle{ //参数 new的时候传的参数 constructor(x,y){ this.x = x; this.y = y; } add(){ return this.x +this.y } } const m = new MathHandle(1,2); m.add(); typeof MathHandle //"function" MathHandle === MathHandle.prototype.constructor;//true m.__proto__=== MathHandle.prototype//true ~~~ **typeof MathHandle //"function" MathHandle === MathHandle.prototype.constructor;//true m.\__proto__=== MathHandle.prototype//true** prototype(显示原型)\__proto__(隐式原型) 3. 语法糖 class完全符合js构造函数原理,因此,class本身是语法糖 写法本质是一样的,但第二种比第一中更加简单易懂 ~~~ class MathHandle { } typeof MathHandle //"function" MathHandle === MathHandle.prototype.constructor;//true ~~~ **class**:本身是一个语法糖,是一个函数 **typeof MathHandle //"function"** class的原型的constructor是构造函数本身 **MathHandle === MathHandle.prototype.constructor;** 这种语法糖,看起来和实际原理不一样的东西,不赞同 形式上强行模仿 java,C#却失去了它的本性和个性 原型的继承 4. 继承 ~~~ function Animal(){ this.eat = function(){ } } function Dog(){ this.bark = function(){ } } Dog.prototype = new Animal(); var hashiqi = new Dog(); ~~~ **Dog.prototype = new Animal();** ~~~ class Animal{ constructor(name){ this.name = name; } eat(){ console.log(this.name+':eat') } } class Dog extends Animal{ constructor(name){ super(name); } say(){ console.log(this.name+':say') } } const dog = new Dog('哈士奇'); dog.say(); dog.eat(); ~~~ **class Dog extends Animal** **super(name)**:被继承的class的constructor class继承:提高阅读体验,与java很像 ### **问题解答** 1. Class在语法上更加贴合面向对象的写法(发展方向) 2. Class实现继承更加易读,易理解,入门容易,学习成本低 3. 更易于写java等后端语言的使用 4. **本质还是语法糖,使用prototype继承** ***** ### **Promise的基本使用** * Callback hell 异步加载: ~~~ function loadImg(src, callback, fail){ var img = document.createElement('img'); img.onload = function(){ callback(img) } img.onerror = function(){ fail() } img.src = src; } var src="..."; loadImg(src,function(img){ console.log(img.width) },function(){console.log('fail')}) ~~~ * Promise语法 ~~~ function loadImg(src){ const promise = new Promise(function(resolve,reject){ var img = document.createElement('img'); img.onload = function(){ resolve(img); } img.onerror = function(){ reject() } img.src = src; } }); return promise; } var src="xxx"; var result = loadImg(src); result.then(function(img){ console.log(img.width); },function(){ console.log('fail') }); result.then(function(height){console.log(img.height)}); ~~~ **const promise = new Promise()** **return promise** ### 问题解答 1. new Promise实例,而且要return 2. new Promise时要传入函数,函数有resolve和reject两个 3. 成功时执行resolve(),失败时执行reject() 4. then监听结果 ***** ### 总结ES6其他常用功能 模块化,class,promise 二八原则:20%的功能满足80%的需求 箭头函数 1. let/const 2. 多行字符串/模板变量(js拼接 **反引号 ${}**)(多行中完整的字符串)(字符串必须单行单行写) 3. 解构赋值(server模块导出一个对象,可用解构后去需要的属性) 4. 块级作用域(之前js没有块级作用域) 5. 函数默认参数 6. 箭头函数(this彻底解决函数指向全局window对象的问题) 7. 扩展运算符(...) 8. ES module **`对象中的扩展运算符(...)用于取出参数对象中的所有可遍历属性,拷贝到当前对象之中`** ~~~ let bar = { a: 1, b: 2 }; let baz = { ...bar }; // { a: 1, b: 2 //相当于 let baz = Object.assign({}, bar); let bar = {a: 1, b: 2}; let baz = {...bar, ...{a:2, b: 4}}; // {a: 2, b: 4} ~~~ **可以将数组转换为参数序列** 用于替换`es5`中的`Array.prototype.slice.call(arguments)`写法 ~~~ function add(x, y) { return x + y; } const numbers \= \[4, 38\]; add(...numbers) // 42 ~~~ 详解: 1. let/const 常量值不可改,报错 2. 多行字符串/模板变量 ~~~ const name = "guo",age =19; const html = `<div> <p>${name}</p> </div>` console.log(html); ~~~ 3. 解构赋值 代码要易读,再精简不易读也不行 ~~~ const obj = {a:10,b:20,c:30}; const {a,c} = obj; const arr =[19,290,39]; const [x,y,z] = arr; ~~~ 4. 块级作用域 ~~~ const obj = {a:19,b:09} for(let item in obj){ } console.log(item);//undefiedn ~~~ 5. 默认参数 ~~~ function(a, b=0){} var b = arguments.length>1&&arguments[1]!==undefined?argument[1]:0; ~~~ ~~~ function fn(a,b){ if(b == null){b=0;} } ~~~ 6. 箭头函数 ~~~ arr.map(item=>item+1) arr.map((item,index)=>{ }) ~~~ ~~~ function fn(){ console.log('real',this);//{a:100} var arr = [1,3]; arr.map(function(){ console.log(this)//window }); arr.map((item,index)=>{ console.log(this);//{a:100} }) } fn.call({a:100}) ~~~ .call:执行时,把{a:100}对象,变成this(强制变成)