ES6原文博客地址:https://finget.github.io/2018/05/10/javascript-es6/现在基本上开发中都在使用ES6,浏览器环境支持不好,可以用babel插件来解决。采用‘二八定律’,主要涉及ES6常用且重要的部分。问题:ES6模块化如何使用,开发环境如何打包Class和普通构造函数有何区别Promise的基本使用和原理总结一下ES6其他常用功能ES6模块化如何使用,开发环境如何打包模块化的基本语法// util1.jsexport default { a : 100}const str = ‘hello’;export default str;// export default const str = ‘hello’; X// util2.jsexport function fn1() { console.log(‘fn1’);}export function fn2() { console.log(‘fn2’);}export const fn3 = ()=> { console.log(‘fn3’);}// index.jsimport str from ‘./util1.js’;import {fn1 , fn2} from ‘./util2.js’;import * as fn from ‘./util2.js’;console.log(str);fn1();fn2();fn.fn1();fn.fn2();export default 默认输出这个,然后在import的时候就会拿到默认输出的内容。例子中默认输出的a=100。export多个内容,在import时需要使用{}进行引用你需要的内容。export和export default与exports和module.exports的区别require: node 和 es6 都支持的引入export / import : 只有es6 支持的导出引入module.exports / exports: 只有 node 支持的导出module.exports 初始值为一个空对象 {}exports 是指向的 module.exports 的引用require() 返回的是 module.exports 而不是 exportsNode里面的模块系统遵循的是CommonJS规范。CommonJS定义的模块分为: 模块标识(module)、模块定义(exports) 、模块引用(require)在nodejs,exports 是 module.exports的引用,初始化时,它们都指向同一个{}对象。对象在JS中属于引用类型,意思就是exports和module.exports是指向同一个内存地址的。看下面的例子:exports.fn = function(){ console.log(‘fn’);}// 这两种情况的效果是一样的,上面说了exports与module.exports初始化同一个对象,所以两种定义方就是给这个同对象定义了一个fn的属性,该属性值为一个函数。module.exports.fn = function(){ console.log('fn');}exports = function(){ console.log('fn');}// 这两种情况就不一样了。上面的exports想当于指向了另一个内存地址。而下面这种情况是可以正常导出的。module.exports = function(){ console.log('fn');}exports对象是当前模块的导出对象,用于导出模块公有方法和属性。别的模块通过require函数使用当前模块时得到的就是当前模块的exports对象。module.exports 的使用// sayHello.jsfunction sayHello() { console.log('hello');}module.exports = sayHello;// app.jsvar sayHello = require('./sayHello');sayHello();定义一个sayHello模块,模块里定义了一个sayHello方法,通过替换当前模块exports对象的方式将sayHello方法导出。在app.js中加载这个模块,得到的是一个函数,调用该函数,控制台打印hello。// sayWorld.jsmodule.exports = function(){ console.log('world');}// app.jsvar sayWorld = require('./sayWorld'); // 匿名替换sayWorld();exports 导出多个变量当要导出多个变量怎么办呢?这个时候替换当前模块对象的方法就不实用了,我们需要用到exports对象。// userExports.jsexports.a = function () { console.log('a exports');} exports.b = function () { console.log('b exports');}// app.jsvar useExports = require('./userExports');useExports.a();useExports.b();// a exports// b exports当然,将useExports.js改成这样也是可以的:// userExports.jsmodule.exports.a = function () { console.log('a exports');} module.exports.b = function () { console.log('b exports');}在实际开发当中可以只使用module.exports避免造成不必要的问题。开发环境配置babelBabel中文网nodejs环境 npm initnpm i babel-core babel-preset-es2015 babel-preset-latest --save-dev创建.babelrc文件npm i --global babel-cli// .babelrc{ "presets": ["es2015","latest"], "plugins": []}webpack四大维度解锁webpack3笔记rollup.jsRollup.js官网npm init安装 rollup.js需要的一些插件npm i rollup rollup-plugin-node-resolve rollup-plugin-babel babel-core babel-plugin-external-helpers babel-preset-latest --save-dev配置 .babelrc配置 rollup.config.jsrollup 功能单一(打包js模块化), webpack功能强大工具尽量功能单一,可继承,可扩展// .babelrc{ "presets":[ ["latest", { "es2015":{ "modules": false } }] ], "plugins":["external-helpers"]}// rollup.config.jsimport babel from 'rollup-plugin-babel';import resolve from 'rollup-plugin-node-resolve';export default { entry: 'src/index.js', format: 'umd', plugins: [ resolve(), babel({ exclude: 'node_modules/**' }) ], dest: 'build/bundle.js'}// package.json..."scripts":{ "start": "rollup -c rollup.config.js"}...npm run start关于JS众多模块化标准没有模块化AMD成为标准,require.js前端打包工具,使得nodejs模块化(CommonJS)可以被使用ES6出现,想统一现在所有模块化标准nodejs积极支持,浏览器尚未统一你可以自造lib,但是不要自造标准!!!Class和普通构造函数有何区别JS构造函数// 构造函数function MathHandle(x, y){ this.x = x; this.y = y;}// 原型扩展MathHandle.prototype.add = function(){ return this.x + this.y;}// 创建实例var m = new ManthHandle(1,2);console.log(m.add()); // 3Class基本语法class MathHandle { // 直接跟大括号 constructor(x, y) { this.x = x; this.y = y; } add() { return this.x + this.y; }}const m = new ManthHandle(1,2);console.log(m.add()); // 3语法糖typeof MathHandle = 'function'MathHandle其实是个function,‘构造函数’MathHandle === MathHandle.prototype.constructor继承原生js继承// 动物function Animal() { this.eat = function() { console.log('animal eat'); }}// 狗function Dog() { this.bark = function(){ console.log('dog bark'); }}// 绑定原型,实现继承Dog.prototype = new Animal();// 实例化一只狗var hashiqi = new Dog();// hashiqi就有了eat方法hashiqi.eat(); // animal eat廖雪峰老师的原型继承:点这里ES6继承class Animal { constructor(name){ this.name = name; } eat() { console.log(
${this.name} eat); }}class Dog extends Animal { // extends 继承 constructor(name){ super(name); // 必须* 记得用super调用父类的构造方法! this.name = name; } say() { console.log(
${this.name} say); }}const dog = new Dog('hashiqi');dog.eat(); // hashiqi eatPromise 的基础使用解决回调地狱(Callback Hell)详细点的Promise:点这里Promise 基础语法new Promise((resolve, reject) => { // 一段耗时很长的异步操作 ..... resolve(); // 数据处理完成 reject(); // 数据处理出错}).then(function A() { // 成功,下一步}, function B(){ // 失败,做相应处理})我最开始接触到Promise的时候,一直傻了吧唧的在想resolve()和reject()在什么时候调用。resolve()和reject()就是为后面then()中的两个函数服务的。resolve和rejectnew Promise((resolve, reject) => { setTimeout(()=>{ resolve('good,我要传给then里的一个函数'); },2000); setTimeout(()=>{ reject('错了,把我给我then里的第二个函数'); },2000);}).then(value => { console.log(value); // good,我要传给then里的一个函数},value => { console.log(value); // 错了,把我给我then里的第二个函数});来个实际的例子/** * 基于jquery封装一个promise ajax请求 * @param {[type]} param [选项] * @return {[type]} [description] */request(param){ return new Promise((resolve,reject) => { $.ajax({ type : param.type || 'get', url : param.url || '', dataType : param.dataType || 'json', data : param.data || null, success:(res)=>{ // 用箭头函数避免this指向问题 if (0 === res.status) { typeof resolve === 'function'&&resolve(res.data, res.msg); // 成功就把请求到的数据用resolve返回,这样就可以在then的第一个函数里拿到值了 } else { typeof reject === 'function'&&reject(res.msg || res.data); // 失败就返回错误信息 } }, error:(err)=>{ // 这个失败是请求失败,上面那个失败是请求成功发送了,但是没有拿到数据失败了 typeof reject === 'function'&&reject(err.statusText); } }) })}ES6常用其他功能let/constlet const与var都是用来定义变量的,不同的是let自带作用域,const不能重复赋值。let name = 'FinGet'while (true) { let name = 'GetFin' console.log(name) //GetFin break}console.log(name) //FinGetlet定义的变量只在包含它的代码块内有用const PI = 3.1415926;PI = 3.14; // 错误多行字符串/模板变量let name = 'FinGet';let age = 22;// jsvar str = '我是'+ name+',今年'+age+'岁'; // 很麻烦let str1 =
我是${name},今年${age}岁; // 简单多了模板字符串就是用
(Tab键上面那个)包含,变量就是用${}`表示解构赋值let obj = { name: ‘FinGet’, age: 22, job: ‘前端’, addr: ‘成都’}let {name,age} = obj;console.log(name); // FinGetconsole.log(age); // 22还可以反过来:let name = ‘FinGet’;let age = 22;let job = ‘前端’;let addr = ‘成都’;let obj = {name,age,job,addr};//obj = {name: ‘FinGet’,age: 22,job: ‘前端’,addr: ‘成都’}块级作用域另外一个var带来的不合理场景就是用来计数的循环变量泄露为全局变量,看下面的例子:// jsvar a = [];for (var i = 0; i < 10; i++) { a[i] = function () { console.log(i); };}a6; // 10let 自带块级作用域// ES6var a = [];for (let i = 0; i < 10; i++) { a[i] = function () { console.log(i); };}a6; // 6原生js想实现这种效果,需要用到闭包:var a = [];for (var i = 0; i < 10; i++) { (function(j){ // 立即执行函数 a[j] = function() { console.log(j); } }(i))}a6; // 6立即执行函数形成了一个块级作用域,将参数j保存了下来,并不会被‘污染’,原生js没有块级作用域,var在for中定义的变量是个全局变量,可以在外部访问,也就可以被改变,所以每次for循环都是重置修改i的值,导致最后只能输出10。函数默认参数与restdefault很简单,意思就是默认值。大家可以看下面的例子,调用animal()方法时忘了传参数,传统的做法就是加上这一句type = type || ‘cat’ 来指定默认值。function animal(type){ type = type || ‘cat’ console.log(type)}animal()如果用ES6我们而已直接这么写:function animal(type = ‘cat’){ console.log(type)}animal(); // cat最后一个rest语法也很简单,直接看例子:function animals(…types){ console.log(types)}animals(‘cat’, ‘dog’, ‘fish’) //[“cat”, “dog”, “fish”]而如果不用ES6的话,我们则得使用ES5的arguments。箭头函数// js函数function (a,b){ console.log(a+b);}// es6箭头函数(a,b) => { console.log(a+b);}把function去掉,在()与{}之间加上=>当我们使用箭头函数时,函数体内的this对象,就是定义时所在的对象,而不是使用时所在的对象。并不是因为箭头函数内部有绑定this的机制,实际原因是箭头函数根本没有自己的this,它的this是继承外面的,因此内部的this就是外层代码块的this。最后创建了一个前端学习交流群,感兴趣的朋友,一起来嗨呀!