原文博客地址:https://finget.github.io/2018/05/10/javascript-es6/
如今基本上开发中都在使用ES6,浏览器环境支持很差,能够用babel插件来解决。
采用‘二八定律’,主要涉及ES6经常使用且重要的部分。javascript
// util1.js export default { a : 100 } const str = 'hello'; export default str; // export default const str = 'hello'; X
// util2.js export function fn1() { console.log('fn1'); } export function fn2() { console.log('fn2'); } export const fn3 = ()=> { console.log('fn3'); }
// index.js import 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
而不是 exports
Node
里面的模块系统遵循的是CommonJS规范。java
CommonJS定义的模块分为: 模块标识(module
)、模块定义(exports
) 、模块引用(require
)
在nodejs,exports
是 module.exports
的引用,初始化时,它们都指向同一个{}
对象。node
对象在JS中属于引用类型,意思就是exports
和module.exports
是指向同一个内存地址的。jquery
看下面的例子:webpack
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对象。
// sayHello.js function sayHello() { console.log('hello'); } module.exports = sayHello; // app.js var sayHello = require('./sayHello'); sayHello();
定义一个sayHello模块,模块里定义了一个sayHello方法,经过替换当前模块exports对象的方式将sayHello方法导出。
在app.js中加载这个模块,获得的是一个函数,调用该函数,控制台打印hello。git
// sayWorld.js module.exports = function(){ console.log('world'); } // app.js var sayWorld = require('./sayWorld'); // 匿名替换 sayWorld();
当要导出多个变量怎么办呢?这个时候替换当前模块对象的方法就不实用了,咱们须要用到exports对象。es6
// userExports.js exports.a = function () { console.log('a exports'); } exports.b = function () { console.log('b exports'); } // app.js var useExports = require('./userExports'); useExports.a(); useExports.b(); // a exports // b exports
固然,将useExports.js改为这样也是能够的:github
// userExports.js module.exports.a = function () { console.log('a exports'); } module.exports.b = function () { console.log('b exports'); }
在实际开发当中能够只使用
module.exports
避免形成没必要要的问题。
Babel中文网web
// .babelrc { "presets": ["es2015","latest"], "plugins": [] }
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
rollup 功能单一(打包js模块化), webpack功能强大
工具尽可能功能单一,可继承,可扩展
// .babelrc { "presets":[ ["latest", { "es2015":{ "modules": false } }] ], "plugins":["external-helpers"] }
// rollup.config.js import 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
// 构造函数 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()); // 3
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
// 动物 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
廖雪峰老师的原型继承: 点这里
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 eat
解决回调地狱(Callback Hell)
详细点的Promise: 点这里
new Promise((resolve, reject) => { // 一段耗时很长的异步操做 ..... resolve(); // 数据处理完成 reject(); // 数据处理出错 }).then(function A() { // 成功,下一步 }, function B(){ // 失败,作相应处理 })
我最开始接触到Promise
的时候,一直傻了吧唧的在想resolve()
和reject()
在何时调用。
resolve()
和reject()
就是为后面then()
中的两个函数服务的。
new 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); } }) }) }
let
const
与var
都是用来定义变量的,不一样的是let
自带做用域,const
不能重复赋值。
let name = 'FinGet' while (true) { let name = 'GetFin' console.log(name) //GetFin break } console.log(name) //FinGet
let
定义的变量只在包含它的代码块内有用
const PI = 3.1415926; PI = 3.14; // 错误
let name = 'FinGet'; let age = 22; // js var str = '我是'+ name+',今年'+age+'岁'; // 很麻烦 let str1 = `我是${name},今年${age}岁`; // 简单多了
模板字符串就是用
`(Tab键上面那个)包含,变量就是用
${}`表示
let obj = { name: 'FinGet', age: 22, job: '前端', addr: '成都' } let {name,age} = obj; console.log(name); // FinGet console.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
带来的不合理场景就是用来计数的循环变量泄露为全局变量,看下面的例子:
// js var a = []; for (var i = 0; i < 10; i++) { a[i] = function () { console.log(i); }; } a[6](); // 10
let 自带块级做用域
// ES6 var a = []; for (let i = 0; i < 10; i++) { a[i] = function () { console.log(i); }; } a[6](); // 6
原生js想实现这种效果,须要用到闭包:
var a = []; for (var i = 0; i < 10; i++) { (function(j){ // 当即执行函数 a[j] = function() { console.log(j); } }(i)) } a[6](); // 6
当即执行函数造成了一个块级做用域,将参数j保存了下来,并不会被‘污染’,原生js没有块级做用域,var
在for
中定义的变量是个全局变量,能够在外部访问,也就能够被改变,因此每次for
循环都是重置修改i
的值,致使最后只能输出10。
default
很简单,意思就是默认值。你们能够看下面的例子,调用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
。
建立了一个前端学习交流群,感兴趣的朋友,一块儿来嗨呀!