本文爲 ES6 系列的第一篇。旨在給新同窗一些指引,帶你們走近 ES6 新特性。
簡要介紹:javascript
什麼是 ES6java
它有哪些「明星」特性node
它能夠運行在哪些環境git
ECMAScript 6(如下簡稱ES6)是JavaScript語言的下一代標準,已經在2015年6月正式發佈了。es6
ECMA-262 標準 第6版。計劃之後每一年發佈一次標準,使用年份做爲標準的版本。由於當前版本是在2015年發佈的,因此又稱ECMAScript 2015。ECMA 的全稱是 European Computer Manufacturers Association(歐洲計算機制造商協會)。ECMA-262 被 ISO 國際標準化組織採納爲 ISO/IEC 16262:2011github
平常討論的 JavaScript 一般還包括 DOM(文檔對象模型)、BOM(瀏覽器對象模型),而 ES6 不包含這些。算法
主流框架全面轉向 ES6瀏覽器
Angular 2性能優化
ReactJs服務器
koa
兼容性 對比表格
本節介紹一些廣爲人知的 ES6 「明星」特性,也就是討論 ES6 時常常說起的一些新特性。固然 ES6 並不只限於這些,還包括不少其餘有用的特性,會在本系列的其餘文章中介紹。
原來的 javascript 中沒有塊級做用域,只有函數級做用域。ES6 中新增了 let 命令,使用 let 命令代替 var 命令聲明變量,具備塊級做用域。
函數級做用域
function test() { var hello = 'world'; console.log(hello); } test(); // 'world' console.log(hello); // Error: hello is not defined
塊級做用域
var
命令
if(true) { var hello = 'world'; console.log(hello); // 'world' } console.log(hello); // 'world'
let
命令
if(true) { let hello = 'world'; console.log(hello); // 'world' } console.log(hello); // Error: hello is not defined
使用 const 命令聲明常量
const STATUS_NOT_FOUND = 404;
常量的值爲只讀,不能修改
STATUS_NOT_FOUND = 200; // SyntaxError: "STATUS_NOT_FOUND" is read-only
傳統的字符串
var name = 'es6'; var sayhello = 'hello, \ my name is ' + name + '.'; console.log(sayhello);
輸出:
hello, my name is es6.
ES6 模板字符串
var name = 'es6'; var sayhello = `hello, my name is ${name}.`; console.log(sayhello);
輸出:
hello, my name is es6.
空格和換行都會被保留
容許使用 =>
定義函數,箭頭函數自動綁定當前上下文 this。
x => x+1
等同於匿名函數
function (x) { return x + 1; }
多個參數:
(a,b) => a+b
等同於
function (a, b) { return a + b; }
多行函數體:
(a,b) => { console.log(a + b); return a + b; }
等同於
function (a, b) { console.log(a + b); return a + b; }
原生的 Promise 實現,再也不須要 bluebird
或 Q+
。
Generator 生成器容許你經過寫一個能夠保存本身狀態的的簡單函數來定義一個迭代算法。和 Generator 一塊兒出現的一般還有 yield。
Generator 是一種能夠中止並在以後從新進入的函數。生成器的環境(綁定的變量)會在每次執行後被保存,下次進入時可繼續使用。generator 字面上是「生成器」的意思,在 ES6 裏是迭代器生成器,用於生成一個迭代器對象。
function *gen() { yield 'hello'; yield 'world'; return true; }
以上代碼定義了一個簡單的 generator,看起來就像一個普通的函數,區別是function關鍵字後面有個*號,函數體內可使用yield語句進行流程控制。
var iter = gen(); var a = iter.next(); console.log(a); // {value:'hello', done:false} var b = iter.next(); console.log(b); // {value:'world', done:false} var c = iter.next(); console.log(c); // {value:true, done:true}
當執行gen()的時候,並不執行 generator 函數體,而是返回一個迭代器 Iterator。迭代器具備 next() 方法,每次調用 next() 方法,函數就執行到yield語句的地方。next() 方法返回一個對象,其中value屬性表示 yield 關鍵詞後面表達式的值,done 屬性表示是否遍歷結束。generator 生成器經過 next 和 yield 的配合實現流程控制,上面的代碼執行了三次 next() ,generator 函數體才執行完畢。
在 JavaScript 中引入 OO 面向對象。其實是語法糖,只是看上去更面向對象而已。也有觀點極力反對 Class,認爲 Class 隱藏了 JavaScript 自己原型鏈的語言特性,使其更難理解。
一半以上庫是按 OO/class 方式寫的,除了jQuery以外,幾乎每一個「嚴肅」的JS基礎庫都有一個Class實現,工具、IDE 更容易識別,JavaScript 引擎性能優化。---- johnhax
ES5
function Point(x,y){ this.x = x; this.y = y; } Point.prototype.toString = function () { return '(' + this.x + ', ' + this.y + ')'; }
ES6
class Point { constructor(x, y) { this.x = x; this.y = y; } toString() { return '('+this.x+', '+this.y+')'; } }
許多JS框架都會實現一套本身的 module/loader 機制。反覆造輪子這也就罷了,更大的問題在於,這些輪子互相都是不兼容的。結果就形成了JS社區的分化和內耗,阻礙了JS庫和組件在較細粒度上的競爭和發展,JS框架和庫的切換成了強迫開發者作出非此即彼的選擇。缺少語言級別的 module,其惡果就是既沒有足夠的標準庫,也很難像其餘語言同樣經過叢林法則發展出事實標準庫。 ---- johnhax
社區主流解決方案有 CommonJS 和 AMD,分別用於服務器端和瀏覽器端,瀏覽器端還有 seajs 遵循的 CMD。
CommonJS
exports.firstName = 'mei'; exports.lastName = 'qingguang'; exports.year = 1988; // or module.exports = { firstName: 'mei', lastName: 'qingguang', year: 1988 } // or module.exports = function() { // do something }
AMD
define(['./a', './b'], function(a, b) { // 依賴必須一開始就寫好 a.doSomething() // 此處略去 100 行 b.doSomething() // ... exports.action = function() {}; })
CMD
define(function(require, exports, module) { var a = require('./a') a.doSomething() // 此處略去 100 行 var b = require('./b') // 依賴能夠就近書寫 b.doSomething() // ... exports.action = function() {}; })
ES6 Module
export 命令 和 import 命令
export var firstName = 'mei'; export var lastName = 'qingguang'; export var year = 1988;
import {firstName, lastName, year} from './profile' console.log(firstName, lastName, year)
模塊總體輸出
var firstName = 'mei'; var lastName = 'qingguang'; var year = 1988; export {firstName, lastName, year};
import * as Profile from './profile' console.log(Profile.firstName, Profile.lastName, Profile.year)
export default 總體輸出
export default function() { console.log('My name is mei qingguang'); };
import sayMyName from './profile' console.log(sayMyName())
能夠在 Node.js 和 io.js 中使用部分 ES6 特性。Node.js 和 io.js 都是使用 V8 引擎做爲 JavaScript 運行環境,io.js 集成了更高版本的 V8 引擎,所以能夠比 Node.js 支持更多的 ES6 特性。
在 Node.js 中,須要使用 --harmony
參數開啓 ES6 特性,包括全部已完成、待完成和修訂中的特性。爲了不用到那些廢棄的特性,能夠經過加相似 --harmony_generators
參數開啓特定的特性。
而在 io.js 中,全部已完成的穩定 ES6 特性都已經默認開啓,不須要加任何運行時參數。而待完成和修訂中的特性也能夠經過特定的參數開啓。
io.js 默認開啓瞭如下 ES6 特性:
block scoping
let
const
function-in-blocks
Classes
Collections
Map
WeakMap
Set
WeakSet
Generators
Binary and Octal literals
Object literal extensions
Promises
New String methods
Symbols
Template strings
有兩個著名的編譯器,能將 ES6 代碼編譯成 ES5 代碼,本節只介紹 Babel。
Babel
Traceur
Babel 從根本上講是一個平臺,這是它與 compile-to-JS 語言 CoffeeScript 和 TypeScript 最大的不一樣。Babel 的插件系統容許開發者自定義代碼轉換器並插入到編譯過程。Babel 還能提高 JavaScript 的執行速度,在編譯時進行性能優化。
編譯單個文件
babel script.js --out-file script-compiled.js
監聽文件變化
babel script.js --watch --out-file script-compiled.js
編譯整個文件夾
babel src --out-dir lib
使用 source map,方便調試
babel script.js --out-file script-compiled.js --source-maps
使用 babel-node
命令代替 node
命令,實時編譯並執行 ES6 代碼。不要在生產環境使用 babel-node
命令,它很是耗內存,而且會拖慢應用的性能。
node app.js
babel-node app.js
使用 require 鉤子,可讓你的應用 require 模塊時自動編譯 ES6 代碼。例如:
run.js
require('babel/register') require('./app.js')
將 run.js
做爲整個應用的入口,就能夠在 app.js
和其餘業務代碼中編寫 ES6 代碼,當代碼被 require
進來時,自動編譯成 ES5 代碼。