ES2015 (原稱 ES6) 是 JavaScript 語言的最佳進展。其中針對 ES5 中需要大量樣板的模式提供新功能和糖。包括類別、箭頭函式和模組。在本集節目中,我們將說明在建構 JavaScript 網頁應用程式時,如何充分運用 ES2015 的各項工具。
使用 Babel 進行轉碼
雖然 JavaScript 引擎在實作 ES2015 原生功能的進度方面表現相當出色,但仍有這個問題。如要立即使用完整的功能,您需要將程式碼編譯為 ES5,以便目前的瀏覽器解讀。值得慶幸的是,Babel 等工具 能輕鬆展開這項程序
在建構程序中使用 Babel
Babel 可讓您採用使用 ES2015 功能編寫的 JavaScript,並將其轉譯回 ES5,以便在目前不支援這些功能的瀏覽器中運作。您可以在建構程序中加入 Babel。
var gulp = require('gulp');
var babel = require('gulp-babel');
gulp.task('default', function () {
return gulp.src('src/app.js')
.pipe(babel())
.pipe(gulp.dest('dist'));
});
Babel 的功能之一是無法傳輸。ES6 中的模組可讓您在檔案之間建立類別及匯出 / 匯入類別。如要傳輸模組透過 Browserify 傳遞 JavaScript,系統會合併檔案,然後透過 Babelify (可處理來自 Browserify 的輸出內容) 傳遞此程式碼。
var babelify = require('babelify');
var source = require('vinyl-source-stream');
var browserify = require('browserify');
gulp.task('babelify', function() {
browserify({ entries: './src.js', debug: true })
.transform(babelify)
.bundle()
.pipe(source('bundle.js'))
.pipe(gulp.dest('./dist/js/'));
});
多個 JavaScript 檔案
上述範例需要您定義特定檔案,這個檔案可能會稍微負擔,Matt 會在 Gulp 中執行以下動作來搜尋及傳輸結尾為 .es6.js 的檔案。
var config = {
src: 'src/scripts',
dest: 'dist/scripts'
};
var es6FileGlob = '/**/*.es6.js';
var gulp = require('gulp');
var plugins = require('gulp-load-plugins')();
var glob = require('glob');
var path = require('path');
var browserify = require('browserify');
var babelify = require('babelify');
var source = require('vinyl-source-stream');
// Takes an array of bundles to run through browserify and babelify
function transpileES6Modules(browserifyFileEntries) {
browserifyFileEntries.forEach(function(fileEntry) {
var browserifyBundle = browserify({
entries: [fileEntry.srcPath]
})
.transform(babelify);
var finalStream = browserifyBundle.bundle()
.on('log', plugins.util.log.bind(plugins.util, 'Browserify Log'))
.on('error', plugins.util.log.bind(plugins.util, 'Browserify Error'))
.pipe(source(fileEntry.outputFilename));
return finalStream.pipe(gulp.dest(fileEntry.dest));
});
}
// This takes a source path and finds all files ending
// with .es6.js and creates the bundles to run through browserify
// and babelify
function handleES6Scripts(srcPath) {
var browserifyFileEntries = [];
var es6Filepaths = glob.sync(srcPath + es6FileGlob);
es6Filepaths.forEach(function(filepath) {
var filename = path.basename(filepath);
var directoryOfFile = path.dirname(filepath);
var relativeDirectory = path.relative(
srcPath,
directoryOfFile);
// Create an object and add to the browserify bundle array
browserifyFileEntries.push({
srcPath: './' + filepath,
outputFilename: filename,
dest: path.join(config.dest, relativeDirectory)
});
});
transpileES6Modules(browserifyFileEntries);
}
gulp.task('scripts:es6', ['scripts:lint'], function(cb) {
handleES6Scripts(config.src);
cb();
});
內裡和樣式檢查
檢查程式碼是否有可能的問題和樣式合規時,您可以採取以下幾種做法。
JSHint 與 JSCS
JSHint 和 JSCS 是當今 JavaScript 樣式檢查最常用的工具。
JSHint 會醒目顯示程式碼中的所有可能問題,並指出任何一般被視為不良做法的模式。
JSCS 會查看程式碼的樣式,包括確保只使用 Tab 或空格,並將空格放在一致的位置。
如要在 ES2015 程式碼上使用 JSHint 和 JSCS,您需要在 .jshintrc
和 .jscsrc
檔案中新增 "esnext": true
ESLint
ESLint 是替代的 Linter 和樣式檢查工具。這項工具能擷取大量蒸汽,在 JSHint 上有了一些實用的功能,例如可以指示您編寫 JavaScript 的環境,以及針對特定問題設定錯誤 / 警告等級。
ESLint 可完全自訂,並提供自訂程式碼檢查規則,讓您完全透過其設定檔關閉或關閉選項。此外,如果您使用的是 React,ESLint 也可以與 JSX 搭配使用。
在建構程序中設定 ESLint 也不難。
var gulp = require('gulp'),
eslint = require('gulp-eslint');
gulp.task('lint', function () {
return gulp.src(['js/**/*.js'])
// eslint() attaches the lint output to the eslint property
// of the file object so it can be used by other modules.
.pipe(eslint())
// eslint.format() outputs the lint results to the console.
// Alternatively use eslint.formatEach() (see Docs).
.pipe(eslint.format())
// To have the process exit with an error code (1) on
// lint error, return the stream and pipe to failOnError last.
.pipe(eslint.failOnError());
});
gulp.task('default', ['lint'], function () {
// This will only run if the lint task is successful...
});
Babel 團隊負責維護 babel-estlint,此工具可讓您使用 ESLint 檢查任何有效的 Babel 程式碼。雖然 ESLint 支援自訂剖析器,但 ESLint 並未直接支援 Babel 支援的部分語法,因此如果您需要進一步彈性,也可以使用這個選項。您也可以透過自訂 .eslintrc
檔案的 parser
區段進行設定:
{
"parser": "babel-eslint",
"rules": {
"strict": 0
}
}
Dan Abramov 在 Lint 例如 It's 2015 中設定 ESLint 和 babel-eslint 大膽的設定。也會探討如何將 SublimeLinter-eslint 整合至您的工作流程,確保 Sublime Text 中的 ES2015 程式碼檢查支援。
應使用下列何者?請試用這些建議,並繼續選擇最適合您的方式
ES2015 語法醒目顯示
當然,建議您確保 ES2015 程式碼的語法正確醒目顯示。我們非常希望使用 babel-sublime,此方法可透過套件控制項安裝。設定時,建議您確實將預設值設為所有需要醒目顯示的檔案。這當然包含 JS,但使用 React 時,也可以涵蓋 JSX。
ES2015 紀錄片
我們向來仰賴 JSDoc 記錄 JavaScript 程式碼。很抱歉,在支援 ES2015 時,仍有尚未解決的問題 (問題已在 JSDoc 3 中解決),但目前仍有日益增加的替代方案,我們會等候中。ESDoc就是其中一個好選擇,而 Jonathan Creamer 最近應該有寫作值得一讀。
使用 Babel 編寫 Gulp.js 檔案
如果打算使用 Gulp 進行建構程序,現在可以使用 Babel 支援的任何語法編寫 Gulpfiles。請在網頁入門套件中完成這項操作,而設定方式相對來說相當簡單。使用最新版本的 Gulp 和 Gulp CLI 時,只需將 gulpfile.js
重新命名為 gulpfile.babel.js
,Gulp 就會使用 Babel 自動解讀及轉譯 ES2015 gulpfile。
廣受喜愛的 ES2015 功能
單元
模組是一種從單一檔案匯出值、函式和類別的方法,您可以將這些項目匯入其他檔案。
export function exampleFunction() {
console.log('I\'m an example. #TrueStory');
}
import { exampleFunction } from './example-function';
import BaseController from './base-controller';
export default class ExampleController extends BaseController {
constructor() {
super();
exampleFunction();
}
doSomething() {
console.log('What should I do? Change the DOM? Print a dancing shark to the console?');
}
}
範本字串
範本字串可讓您將字串的通訊埠替換為變數。
// Simple string substitution
var name = "Brendan";
console.log('Yo, ${name}!');
// => "Yo, Brendan!"
範本字串的優點在於替換是 JavaScript 執行,也就是說,您可以使用函式或內嵌運算式。
var a = 10;
var b = 10;
console.log('a+b = ${a+b}.');
//=> a+b = 20.
function fn() { return "I am a result. Rarr"; }
console.log('foo ${fn()} bar');
//=> foo I am a result. Rarr bar.
如要進一步瞭解,請參閱 Addy 撰寫的實用網誌文章。
快速物件常值
如果變數的名稱與您希望物件的索引鍵相同,則可使用物件常值,就不必在建立物件時定義索引鍵和值。
說明:
function createObject(name, data) {
return { name: name, data: data };
}
受限模式:
function createObject(name, data) {
return { name, data };
}
運算屬性名稱
ES2015 的這項功能可讓您在物件上動態建立屬性名稱。Mozilla 文件是絕佳的資訊來源,提供了這個絕佳範例。
var a = {
["foo" + ++i]: i,
["foo" + ++i]: i,
["foo" + ++i]: i
};
console.log(a.foo1); // 1
console.log(a.foo2); // 2
console.log(a.foo3); // 3
脂肪箭頭函式
脂肪箭頭函式可讓您快速編寫函數,其中:
button.addEventListener('click', function(event) {
console.log('The button has received a click', event);
});
受限模式:
button.addEventListener('click', (event) => {
console.log('The button has received a click', event);
});
除了使用較短的語法外,使用脂肪箭頭函式還有一個好處,就是該物件的範圍與包容的陳述相同。也就是說,您不需要對函式呼叫 .bind(this) ,或建立 = this 的變數。
更多資訊的連結
Addy 的 ES6 Tools 存放區
Addy 一直忙於保留一份 ES2015 工具清單。如果上述工具不適合您,或許您會使用 Grunt,而非 Gulp,或許能找到答案。
https://github.com/addyosmani/es6-tools
上述內容也包含其他 Babel 工具的連結,可協助進行單元測試和其他工作。
推薦閱讀的書籍
您可以免費線上瀏覽兩本書,進一步瞭解 ES2015。瞭解 ECMAScript 6 (由 Nicholas C 撰寫)。Zakas 和 Exploring ES6 (探索 ES6),作者:Axel Rauschmayer。
巴貝爾塔
如果您想在指令列中學習 ES2015 功能,請看 tower-of-babel 提供的一系列練習。所有人員都會逐步瞭解如何使用 Babel
其他感興趣的資源: