原文博客地址: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
。
建立了一個前端學習交流羣,感興趣的朋友,一塊兒來嗨呀!