Các cách thực tế để viết ngôn ngữ lập trình JavaScript tốt hơn (P1)

Các cách thực tế để viết ngôn ngữ lập trình JavaScript tốt hơn (P1)

Chia sẻ kiến thức 11/01/2022

Code JavaScript của bạn cần phải gọn gàng, dễ đọc. Nhưng để viết được những dòng code JavaScript đẹp đó thực sự là nghệ thuật.

>> Các cách thực tế để viết ngôn ngữ lập trình JavaScript tốt hơn (P2)

JavaScript đang ngày càng phát triển và trở nên quen thuộc đối với lập trình viên. Nó đã xuất hiện khắp nơi, xung quanh cuộc sống của chúng ta với ứng dụng như: Website, Web Application, Game, IoT, Mobile Application,… Tất cả nhà phát triển luôn muốn viết được dòng code đẹp, gọn gàng để giới thiệu đến khách hàng và người dùng. Để làm được điều đó, ta cần lựa chọn phương pháp phù hợp. Trong bài viết này, FUNiX sẽ giới thiệu những phương pháp để viết JavaScript tốt hơn.

1. Sử dụng TypeScript

Điều số một bạn có thể làm để cải thiện JavaScript của mình là không viết code. TypeScript (TS) là tập “được biên dịch” của JavaScript (bất kỳ thứ gì chạy trong JavaScript đều chạy trong TS). TS bổ sung một hệ thống đánh máy toàn diện trên trải nghiệm JavaScript. 

Trong một thời gian dài, sự hỗ trợ của TS không thực sự nhất quán nên người dùng thấy không thoải mái khi làm việc. Nhưng hiện nay vấn đề này đã được giải quyết và hầu hết Framework Support hỗ trợ TS.

1.1 TypeScript là kiểu an toàn (Type Safety)

Sử dụng TypeSafe để viết Javasript
Sử dụng TypeSafe để viết Javasript.

Kiểu an toàn (Type Safety) là quá trình trong đó trình biên dịch xác minh tất cả kiểu đang được dùng một cách chính xác trong một đoạn code. Nói cách khác, nếu bạn tạo một hàm foo để lấy một số:

function foo(someNum: number): number {

 return someNum + 5;

}

Đó chính là chức năng của foo gọi số chứ không phải định dạng khác. Ví dụ:

  • Chính xác

console.log(foo(2)); // prints “7”

  • Không chính xác

console.log(foo(“two”)); // invalid TS code

Ngoài việc phải mất thời gian để thêm vào đoạn code, Type Safety không có một nhược điểm nào. Nhưng nó mang lại rất nhiều lợi ích, nên đây là công cụ mà bạn không thể bỏ qua. Ví dụ: Type safety cung cấp chức năng bảo vệ bổ sung để hạn chế sự cố. Đây là một trong những đặc điểm mà ngôn ngữ không có quy luật như JavaScript cần.

1.2 Các kiểu (Style) giúp cho việc tái cấu trúc ứng dụng có dung lượng lớn

Tái cấu trúc ứng dụng JavaScript có dung lượng lớn là điều rất khó khăn. Hầu hết sự phức tạp của công việc tái cấu trúc là không thể thực hiện khai báo hàm (function signatures). Bởi vì một hàm JavaScript sẽ không bao giờ bị sai hoàn toàn. Ví dụ: Nếu bạn có một hàm myAPI được sử dụng bởi 1000 dịch vụ khác nhau:

function myAPI(someNum, someString) {

 if (someNum > 0) {

  leakCredentials();

 } else {

  console.log(someString);

 }

}

Nếu chúng ta thay đổi cách gọi hàm một chút:

function myAPI(someString, someNum) {

 if (someNum > 0) {

  leakCredentials();

 } else {

  console.log(someString);

 }

}

Bạn cần chắc chắn 100% mỗi nơi sử dụng chức năng này, chúng ta đều cập nhật chính xác cách dùng. Nếu lập trình viên bỏ sót một trong những thông tin, nó khiến dữ liệu đăng nhập của bạn sẽ bị rò rỉ. Dưới đây sẽ là kịch bản tương tự với TS:

  • Trước

function myAPITS(someNum: number, someString: string) { … }

  • Sau

function myAPITS(someString: string, someNum: number) { … }

Chúng ta thấy, hàm myAPITS đã có sự thay đổi giống như JavaScript. Nhưng thay vì tạo ra JavaScript hợp lệ, code này sẽ xây dựng nên JavaScript không hợp lệ. Vì hàng nghìn nơi nó được sử dụng đang cung cấp sai TypeScript. 

Như trước đây ta có trao đổi về của Safe TypeScript, hàng nghìn trường hợp sẽ chặn quá trình biên dịch và giúp thông tin đăng nhập sẽ không bị rò rỉ.

1.3 TypeScript nhóm kỹ thuật trao đổi dễ dàng hơn

Khi TS được thiết lập chính xác, bạn sẽ cần xác định trước giao diện và lớp. Nếu không bạn sẽ rất khó để viết code. Điều này cung cấp cho người dùng cách để chia sẻ cấu trúc ngắn gọn hơn. Trước khi sử dụng TS, ta phải có giải pháp cho vấn đề này, nhưng chúng khá phức tạp và gây khó khăn cho nhà phát triển. Ví dụ: Nếu muốn đề xuất một kiểu Request mới cho chương trình hỗ trợ của mình, bạn có thể gửi thông tin sau bằng TS:

interface BasicRequest {

 body: Buffer;

 headers: { [header: string]: string | string[] | undefined; };

 secret: Shhh;

}

Dù vẫn phải viết code, nhưng ta có thể chia sẻ quá trình làm việc. Đồng thời nhận phải hồi từ đồng nghiệp mà không mất quá nhiều thời gian. Chúng ta không biết liệu TS có ít xảy ra lỗi hơn JavaScript hay không. Nhưng bạn tin tưởng rằng việc xác định trước giao diện và API sẽ mang lại dòng code tốt hơn.

Nhìn chung, TS là lựa chọn thay thế hoàn hảo và dễ sử dụng. Hiện nay, hầu hết dự án đều sử dụng TS, nhưng lập trình viên vẫn không cảm thấy khó chịu với cách làm việc với JavaScript thông thường.

2. Sử dụng các tính năng hiện đại

Sử dụng các tính năng hiện đại để viết ngôn ngữ JavaScript

JavaScript là một trong những ngôn ngữ được nhà phát triển áp dụng phổ biến nhất trên thế giới. Trong thời gian gần đây, nó đã có nhiều bổ sung và thay đổi (về mặt kỹ thuật có thể kể đến ECMAScript). Những bản cập nhật này sẽ làm thay đổi trải nghiệm của các nhà phát triển. Nhưng nếu Developer làm việc với JavaScript chỉ trong một đến hai năm gần đây, bạn không thể cảm nhận những điều chỉnh đó. 

Nếu là người mới tiếp xúc với JavaScript, bạn sẽ không biết đâu sẽ là tính năng mang lại hiệu quả cao và đâu sẽ là chức năng nên bỏ qua. Một số chức năng dưới đây chắc chắn sẽ cần thiết khi bạn viết code.

2.1 Async và await

Trong một thời gian dài lệnh Callback được thực hiện theo Event Driven (mô hình hướng sự kiện) và không đồng bộ.

  • Traditional Callback

makeHttpRequest(‘google.com’, function (err, result) {

 if (err) {

  console.log(‘Oh boy, an error’);

 } else {

  console.log(result);

 }

});

Để giải quyết vấn đề với lệnh Callback, JavaScript đã được thêm vào một concept (khái niệm) và Promises (lời hứa) 

  • Promises 

makeHttpRequest(‘google.com’).then(function (result) {

 console.log(result);

}).catch(function (err) {

 console.log(‘Oh boy, an error’);

});

Ưu điểm lớn nhất của Promises so với callback là tính dễ đọc và khả năng đảm bảo (chainability) rất tốt.

Mặc dù Promises rất tốt nhưng nhà phát triển lại có những mong muốn cao hơn. Cụ thể, lập trình viên đã yêu cầu một giải pháp để thay thế cho mô hình Promise. Điều này khiến JavaScript phải thêm một giải pháp mới để dùng Promise trong phiên bản ECMAScript là async và await:

  • async và await

try {

 const result = await makeHttpRequest(‘google.com’);

 console.log(result);

} catch (err) {

 console.log(‘Oh boy, an error’);

}

Lưu ý: Bất kỳ điều gì bạn await phải được khai báo async. Nó là yêu cầu bắt buộc của makeHttpRequest:

async function makeHttpRequest(url) {

 // …

}

Cũng có thể có await một Promise trực tiếp, vì hàm async chỉ có chức năng là một trình chứa Promise. Có nghĩa là code async/await và code Promise sẽ có chức năng tương đương nhau. Vậy nên, bạn thoải mái dùng async/await mà không gặp bất kỳ vấn đề gì.

2.2 Let và const

Trước đây thì var là từ khóa duy nhất được dùng để khai báo biến trong JavaScript. Nhưng kể từ khi ECMAScript được ra mắt, ngôn ngữ này đã được bổ sung thêm từ khóa const let.

Một trong những nguyên nhân khiến let thay thế var là vì biến let được khai báo sẽ có scope là block scoped chứ không phải locally hay globally scoped.

 let greeting = “say Hi”;

  let times = 4;

  if (times > 3) {

    let hello = “say Hello instead”;

    console.log(hello); // “say Hello instead”

  }

  console.log(hello); // hello is not defined

Chúng ta thấy, đối với biến có scoped là block scoped. Nếu scope được khai báo thì sẽ không để dùng được nữa. Tuy nhiên, đối với block khác nhau thì việc tái khai báo biến sẽ không xảy ra sự cố vì với mỗi biến, mỗi scoped được xét là một biến khác riêng biệt.

Bên cạnh biến let thì biến const cũng có scoped là block scoped và hosting. Trong const, nếu trường hợp kiểu biến là Primitive (bao gồm number, boolean, string, null và undefined), chúng ta sẽ không thể cập nhật giá trị mới để thay thế cho giá trị trước đó của biến:

 const greeting = “say Hi”;

  greeting = “say Hello instead”; // error : Assignment to constant variable. 

 

  ————————————————

 

  const greeting = “say Hi”;

  const greeting = “say Hello instead”; // error : Identifier ‘greeting’ has already been declared

Đối với trường hợp kiểu kiến là reference (bao gồm array, object và function) thì không thể tái khai báo giá trị của nó. Nhưng bạn vẫn cập nhật được giá trị cho thuộc tính của biến.

3. Hàm mũi tên

Sử dụng hàm mũi tên để viết JavaScript
Sử dụng hàm mũi tên để viết JavaScript

Hàm mũi tên (arrow function) là phương pháp ngắn gọn để khai báo hàm ẩn danh (anonymous function). Hàm ẩn danh là thuật ngữ mô tả hàm không được đặt tên rõ ràng. Chúng sẽ được chuyển dưới dạng callback hoặc event hook.

  • Hàm ẩn danh

someMethod(1, function () { // has no name

 console.log(‘called’);

});

Nếu xét code trên thì chúng ta sẽ thấy không có vấn đề gì. Đây là một đặc điểm của hàm ẩn danh, điều này sẽ dẫn đến các sự cố không mong muốn. Nhưng với hàm mũi tên, bạn sẽ không phải lo lắng về vấn đề với hàm ẩn danh nữa. Dưới đây là một code tương tự được triển khai với hàm mũi tên.

  • Hàm mũi tên

someMethod(1, () => { // has no name

 console.log(‘called’);

});

Hàm mũi tên ngắn hơn rất nhiều và xác định scope thực tế hơn rất nhiều. Hạm này kế thừa this từ scope mà chúng đã được xác định. 

Trong một số trường hợp hàm mũi tên ngắn gọn hơn:

const added = [0, 1, 2, 3, 4].map((item) => item + 1);

console.log(added) // prints “[1, 2, 3, 4, 5]”

Hàm mũi tên nằm trên một dòng bao gồm một câu lệnh ngầm là return. Nó có dòng đơn này không cần dấu ngoặc hoặc dấu chấm phẩy.

Nhưng bạn cần phân biệt rõ ràng vì đây không phải là một tình huống var. Vẫn sẽ có trường hợp dùng hợp lệ hàm vô danh tại (cụ thể là lớp). Bên cạnh đó, nếu để ý ta sẽ thấy rằng, việc chỉ sử dụng mặc định một hàm mũi tên thì sẽ xảy ra ít lỗi hơn nhiều so với hàm ẩn danh.

3.1 Sử dụng spread operator (…) 

Rất nhiều lập trình viên sẽ lấy ra cặp từ khóa / giá trị của một đối tượng và cho chúng làm biến con của đối tượng khác. Trước đây, cũng có một số cách để thực hiện điều này, nhưng chúng đều là những phương pháp khá phức tạp:

const obj1 = { dog: ‘woof’ };

const obj2 = { cat: ‘meow’ };

const merged = Object.assign({}, obj1, obj2);

console.log(merged) // prints { dog: ‘woof’, cat: ‘meow’ }

Nhưng nhiều khi chúng cũng hoạt động liền mạch với mảng:

const arr1 = [1, 2];

const arr2 = [3, 4];

console.log([ …arr1, …arr2 ]); // prints [1, 2, 3, 4]

Đây không phải là tính năng quan trọng nhất của JavaScript. Nhưng nó sẽ là một trong những tính năng ưu tiên của nhiều lập trình viên.

3.2 Ký tự chuỗi hay ký tự mẫu ( Template Literals or Template Strings)

Chuỗi (Strings) là một trong những kiểu lập trình phổ biến nhất. Nhưng nhiều khai báo nguyên bản vẫn chưa được hỗ trợ cho các ngôn ngữ. Trong một thời gian dài JavaScript yêu cầu phải “crappy string”. Nhưng ngôn ngữ này đã bổ sung các ký tự mẫu vào danh mục của nó, giúp ta giải quyết hai vấn đề lớn nhất của việc viết chuỗi là: Thêm nội dung động và viết chuỗi nối nhiều dòng:

const name = ‘Ryland’;

const helloString =

`Hello

 ${name}`;

3.3 Destructuring Objects

Destructuring Objects (cấu trúc đối tượng) là cách để trích xuất giá trị từ tập hợp dữ liệu (đối tượng, mảng,…) mà không cần phải lặp lại dữ liệu hoặc truy cập từ khóa của nó một cách cụ thể.

  • Cách thực hiện cũ

function animalParty(dogSound, catSound) {}

const myDict = {

 dog: ‘woof’,

 cat: ‘meow’,

};

animalParty(myDict.dog, myDict.cat);

  • Destructuring

function animalParty(dogSound, catSound) {}

const myDict = {

 dog: ‘woof’,

 cat: ‘meow’,

};

const { dog, cat } = myDict;

animalParty(dog, cat);

Hoặc bạn có thể xác định Destructuring Objects theo một chữ ký của một hàm như sau:

  • Destructuring 2

function animalParty({ dog, cat }) {}

const myDict = {

 dog: ‘woof’,

 cat: ‘meow’,

};

animalParty(myDict);

Hay bạn có thể xác định Destructuring Objects theo mảng như:

  • Destructuring 3

[a, b] = [10, 20];

console.log(a); // prints 10

Ngoài ra, có nhiều tính năng khác mà bạn sử dụng. Dưới đây là một số gợi ý đáng để tham khảo:

  • Rest Parameter
  • Import Over Require
  • Array Element Find

FUNiX vừa cung cấp 03 cách để bạn có thể viết JavaScript tốt hơn là: Sử dụng TypeScript, sử dụng tính năng hiện đại và hàm mũi tên. Nếu áp dụng một cách phù hợp, chúng sẽ giúp nâng cao kỹ năng viết code của bạn hơn rất nhiều. Nhưng để lập trình viên có thêm nhiều lựa chọn và tạo ra được nhiều dòng code thú vị hơn. Bài viết sau, FUNiX giới thiệu các phương pháp được nhiều nhà phát triển cấp cao sử dụng để viết JavaScript áp dụng trong nhiều năm liền.

 

Công Sơn

Nguồn tham khảo: https://stackoverflow.blog/2019/09/12/practical-ways-to-write-better-javascript/

ĐĂNG KÝ TƯ VẤN HỌC LẬP TRÌNH TẠI FUNiX

Bình luận (
0
)

Bài liên quan

  • Tầng 0, tòa nhà FPT, 17 Duy Tân, Q. Cầu Giấy, Hà Nội
  • info@funix.edu.vn
  • 0782313602 (Zalo, Viber)        
Chat Button
FUNiX V2 GenAI Chatbot ×

yêu cầu gọi lại