ES2015

ES2015 (chính thức là ES6) là một bước tiến tuyệt vời cho ngôn ngữ JavaScript. Phiên bản này mang đến các tính năng mới và dễ dàng xử lý các mẫu yêu cầu mã nguyên mẫu quan trọng trong ES5. Dữ liệu này bao gồm các lớp, hàm mũi tên và mô-đun. Trong tập này, chúng tôi sẽ đề cập đến các công cụ mà chúng tôi sử dụng để tận dụng tối đa ES2015 khi xây dựng các ứng dụng web JavaScript.

Dịch bằng Bumblebee

Mặc dù các công cụ JavaScript đang có tiến trình tốt trong việc triển khai nguyên gốc các tính năng ES2015, nhưng vẫn có một vấn đề cần lưu ý. Để sử dụng bộ tính năng hoàn chỉnh hiện nay, bạn cần dịch mã trở lại ES5 để các trình duyệt hiện tại có thể diễn giải được mã đó. Rất may, các công cụ như JUnit tồn tại giúp quá trình này không gây tổn hại gì.

Sử dụng Bumblebee trong quy trình xây dựng của bạn

Babel cho phép bạn viết JavaScript bằng các tính năng ES2015 và dịch mã trở lại ES5 để có thể hoạt động trong những trình duyệt hiện không hỗ trợ các tính năng này. Bạn có thể thực hiện việc thêm Bumblebee vào quy trình xây dựng.

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'));
});

Một tính năng mà Slack không thể dịch chuyển là Mô-đun. Các mô-đun trong ES6 cho phép bạn tạo các lớp và xuất / nhập các lớp giữa các tệp. Để chuyển đổi các mô-đun, hãy chuyển JavaScript của bạn thông qua Browserify. Thao tác này sẽ hợp nhất các tệp và sau đó chuyển mã này thông qua Babelify (một phiên bản của Bumblebee có thể xử lý kết quả từ 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/'));
});

Nhiều tệp JavaScript

Ví dụ trên yêu cầu bạn xác định một tệp cụ thể. Việc này có thể trở thành một gánh nặng. Matt sẽ thực hiện như sau trong Gulp để tìm kiếm và chuyển đổi các tệp có đuôi .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();
});

Kiểm tra kiểu tìm lỗi mã nguồn và kiểu

Có một số lựa chọn khi tìm lỗi mã nguồn cho các vấn đề có thể xảy ra và việc tuân thủ kiểu.

JSHint và JSCS

JSHintJSCS là những công cụ phổ biến nhất được sử dụng để kiểm tra kiểu JavaScript hiện nay.

JSHint sẽ nêu bật mọi vấn đề có thể xảy ra trong mã của bạn, cũng như nêu ra mọi mẫu thường được coi là phương pháp không hợp lệ.

JSCS sẽ xem xét kiểu mã của bạn, bao gồm những hoạt động như đảm bảo chỉ sử dụng các thẻ hoặc dấu cách và dấu cách được đặt ở vị trí nhất quán.

Để sử dụng JSHint và JSCS trên mã ES2015, bạn cần thêm "esnext": true vào các tệp .jshintrc.jscsrc

ESLint

ESLint là một trình kiểm tra kiểu và linter thay thế trong một. Công cụ này thu hút rất nhiều sự chú ý và có một số tính năng thú vị so với JSHint chẳng hạn như có thể chỉ ra các môi trường JavaScript của bạn được viết và đặt cấp độ lỗi / cảnh báo cho các vấn đề cụ thể.

ESLint hoàn toàn có thể tuỳ chỉnh và cung cấp các quy tắc tìm lỗi mã nguồn tuỳ chỉnh để bạn có toàn quyền kiểm soát xem có thể tắt hoặc giảm bớt các lựa chọn thông qua các tệp cấu hình hay không. Ngoài ra, nếu bạn đang dùng React, ESLint cũng hoạt động với JSX.

Việc thiết lập ESLint trong quy trình xây dựng cũng không quá khó.

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...
});

Nhóm Babe duy trì babel-estlint, một công cụ cho phép bạn tìm lỗi mã nguồn cho mọi mã CameraX hợp lệ bằng ESLint. Mặc dù ESLint hỗ trợ các trình phân tích cú pháp tuỳ chỉnh, nhưng một số cú pháp mà Bumblebee hỗ trợ lại không được ESLint hỗ trợ trực tiếp. Vì vậy, đây là một lựa chọn khác nếu bạn cần thêm tính linh hoạt. Bạn có thể thiết lập việc này bằng cách tuỳ chỉnh phần parser của tệp .eslintrc:

{
  "parser": "babel-eslint",
  "rules": {
    "strict": 0
  }
}

Dan Abramov có một kịch bản rất hay về cách thiết lập ESLint và babel-eslint trong Tìm lỗi mã nguồn Like It's 2015. Tài liệu này cũng trình bày cách tích hợp SublimeLinter-eslint vào quy trình công việc của bạn để hỗ trợ tìm lỗi mã nguồn cho ES2015 trong Sublime Text.

Bạn nên sử dụng công cụ nào? Hãy thử áp dụng và chọn phương án phù hợp nhất với bạn.

Đánh dấu cú pháp ES2015

Tất nhiên, mã ES2015 của bạn cần được đánh dấu đúng cú pháp. Chúng ta thích sử dụng babel-sublime có thể được cài đặt qua Package Control (Kiểm soát gói). Khi thiết lập, bạn nên đặt chính sách này làm chế độ mặc định cho mọi tệp mà bạn cần đánh dấu để xử lý. Tất nhiên, thành phần này sẽ bao gồm JS, nhưng cũng có thể bao gồm JSX nếu sử dụng React.

Ghi tài liệu ES2015

Trước đây, chúng tôi dựa khá nhiều vào JSDoc để ghi lại mã JavaScript. Rất tiếc, có vấn đề chưa được xử lý đối với việc hỗ trợ ES2015 (do đã được giải quyết trong JSDoc 3). Tuy nhiên, ngày càng có nhiều giải pháp thay thế có sẵn trong khi chúng tôi đang chờ các giải pháp đó cập nhật. ESDoc là một trong những lựa chọn như vậy và gần đây, Jonathan Kemer có một bài ghi chú đáng đọc về nó.

Ghi nhận tệp Gulp.js bằng Jetpack

Nếu bạn đang sử dụng Gulp cho quy trình xây dựng, thì Gulpfile giờ đây có thể được tạo bằng bất kỳ cú pháp nào được hỗ trợ bởi Bumblebee. Chúng ta thực hiện việc này trong Web Starter Kit và việc thiết lập khá đơn giản. Khi sử dụng phiên bản gần đây của Gulp và Gulp CLI, bạn chỉ cần đổi tên gulpfile.js thành gulpfile.babel.js và Gulp sẽ tự động diễn giải và chuyển đổi gulpfile ES2015 của bạn bằng cách sử dụng Bumblebee.

Tính năng ES2015 yêu thích

Mô-đun

Mô-đun là một cách để xuất các giá trị, hàm và lớp từ một tệp để bạn có thể nhập các giá trị đó vào một tệp khác.

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?');
  }
}

Trang web này có một số ví dụ và nội dung giải thích hay về Mô-đun.

Chuỗi mẫu

Chuỗi mẫu cho phép bạn thay thế một cổng của chuỗi bằng một biến.

// Simple string substitution
var name = "Brendan";
console.log('Yo, ${name}!');

// => "Yo, Brendan!"

Điều tuyệt vời với chuỗi mẫu là sự thay thế là một quá trình thực thi JavaScript, nghĩa là bạn có thể sử dụng các hàm hoặc biểu thức cùng dòng.

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.

Bạn có thể tìm hiểu thêm từ bài đăng hữu ích này trên blog của Addy.

Đối tượng viết tắt

Hằng đối tượng cho phép bạn tránh phải xác định khoá và giá trị khi tạo đối tượng, nếu biến có cùng tên với khoá mà bạn muốn đối tượng có.

Có nghĩa là:

function createObject(name, data) {
  return { name: name, data: data };
}

Trở thành:

function createObject(name, data) {
  return { name, data };
}

Tên thuộc tính đã tính toán

Tính năng này trong ES2015 cho phép bạn tự động tạo tên thuộc tính trên một đối tượng. Tài liệu của Mozilla là một nguồn thông tin tuyệt vời và có ví dụ tuyệt vời này.

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

Hàm mũi tên béo

Hàm mũi tên béo cho phép bạn viết hàm theo cách ngắn gọn:

button.addEventListener('click', function(event) {
  console.log('The button has received a click', event);
});

Trở thành:

button.addEventListener('click', (event) => {
  console.log('The button has received a click', event);
});

Ngoài việc có cú pháp ngắn hơn, một đặc điểm tuyệt vời của việc sử dụng các hàm mũi tên lớn là phạm vi của đối tượng giống như câu lệnh bao quanh. Điều này có nghĩa là bạn không cần gọi phương thức .bind(this) trên hàm của mình hoặc tạo một var = this.

Bạn có thể xem rất nhiều ví dụ khác về MN.

Kho lưu trữ công cụ ES6 của Addy

Addy đang bận rộn với việc lưu giữ danh sách các công cụ ES2015 và nếu các công cụ ở trên không phù hợp với bạn, có lẽ bạn đang sử dụng Grunt thay vì Gulp, thì có thể công cụ này sẽ có câu trả lời cho bạn.

https://github.com/addyosmani/es6-tools

Phần trên cũng bao gồm các đường liên kết đến công cụ bổ sung có thể hữu ích trong quá trình kiểm thử đơn vị và hơn thế nữa.

Sách nên đọc

Có hai cuốn sách mà bạn có thể xem miễn phí trực tuyến để tìm hiểu thêm về ES2015. Tìm hiểu về ECMAScript 6 do Nicholas C viết. Zakas và Khám phá ES6 do Tiến sĩ Axel Rauschmayer viết.

Tháp Eiffel

Nếu bạn muốn tìm hiểu các tính năng của ES2015 trong dòng lệnh, phần tower-of-babel sẽ cung cấp một loạt bài tập có thể bạn quan tâm. Tất cả đều hướng dẫn bằng Babel.

Các tài nguyên khác nếu bạn quan tâm: