Cách biểu diễn function và mũi tên function

Trong Javascript thì function không phải là một "phép màu" , nhưng chắc hẳn các bạn cũng đã biết, nó có một giá trị, sức mạnh đặc biệt.

Cú pháp tạo ra function như sau:

function sayHi(){
alert('hello Techmaster')
}

Còn có một kiểu biểu diễn function nữa, nó trông như sau:

let sayHi = function() {
  alert( "Hello Techmaster" );
};

Đó, function được tạo, và nó được gắn với một biến. Điều này có nghĩa là function dù có như thế nào đi nữa thì nó cũng chỉ là một giá trị của biến sayHi

Chúng ta thậm chí còn có thể in giá trị của biến đó ra

function sayHi() {
  alert( "Hello" );
}

alert( sayHi ); // Hiển thị toàn bộ function

Lưu ý rằng nếu chúng ta không đặt dấu ngoặc () sau khi gọi hàm thì hàm không được thực hiện. Mà chỉ alert ra giá trị text của hàm, có rất nhiều ngôn ngữ, chỉ cần gọi đến tên function là chạy, nhưng javascipt không vậy.

Chúng ta cũng có thể coppy gán một function sang một biến khác

function sayHi() {   // (1) Khởi tạo function
  alert( "Hello" );
}

let func = sayHi;    // (2) copy

func(); // Hello     // (3) chạy bản copy (có hoạt động)!
sayHi(); // Hello    //     ở đây cũng vẫn hoạt động (tại sao không chứ)

Dưới đây là mô tả của ví dụ trên

1. Đầu tiên function được khởi tạo (1), và đặt cho nó một tên là sayHi

2. Dòng (2), copy vào biến func

Lưu ý: ở đây là copy chứ không phải gán nó bằng function sayHi(). Không được có dấu ngoặc ở sau tên function. Nếu không thì func sẽ là kết quả của function sayHi() chứ không phải được copy nội dung.

3. Bây giờ thì chúng ta có thể gọi chúng bằng cả 2 cái tên sayHi() và func()

Callback functions

Nào, hãy cùng xem nhiều hơn về cách gán biến của function và cách đặt chúng.

Chúng ta sẽ viết một function là ask(question, yes, no) với 3 tham số truyền vào:

question: text của câu hỏi

yes: Function chạy nếu câu trả lời là yes

no: Function chạy nếu câu trả lời là no

Function sẽ hỏi câu hỏi , sau đó sẽ phụ thuộc vào câu trả lời, rồi sẽ gọi yes() hay no():

function ask(question, yes, no) {
  if (confirm(question)) yes()
  else no();
} // Cửa sổ hiện lên với 2 lựa chọn OK và Cancel, tương ứng với 2 hàm yes(), no() được chạy. 
// Ví dụ:

function showOk() {
  alert( "You agreed." );
}

function showCancel() {
  alert( "You canceled the execution." );
}

// usage: functions showOk, showCancel được đặt vào như tham số
ask("Do you agree?", showOk, showCancel);

Trước khi chúng ta tìm hiểu về cách viết ngắn gọn hơn, thì điều cần nói ở đây là trong vieejc triển khai thực tế là các hàm phức tạp hơn nhiều để tương tác với người dùng. Và láy dữ liệu từ phía backend.

Khai báo function và biểu thức hàm (Function Declaration và Function Expression)

Hãy xem sự khác biệt chính gữa 2 loại này

Đầu tiên, xét về cú pháp.

Function Declaration :

// Function Declaration
function sum(a, b) {
  return a + b;
}

Function Expression: Một function được tạo bên trong một biết thức khác , hoặc một cú pháp khác nào đó. Trong trường hợp này function được tạo bên trong biểu thức gán "=".

// Function Expression
let sum = function(a, b) {
  return a + b;
};

Function Expression được tạo khi việc biểu diễn qua nó, và sẽ có tính sử dụng từ đó về sau.

Function Declaration được sử dụng trong toàn bộ khối lệnh bên trong.

Nói cách khác thì trước khi Javascript chạy tập code trong đó, trước tiên nó sẽ tìm function được khai báo và tạo ra các hàm. Chúng ta hãy nghĩ đó giống như một giai đoạn khởi tạo.

Ví dụ:

sayHi("John"); // Hello, John

function sayHi(name) {
  alert( `Hello, ${name}` );
}

Nếu là một Function Expression, thì sẽ không hoạt động.

sayHi("John"); // error!

let sayHi = function(name) {  
  alert( `Hello, ${name}` );
};

Vậy khi nào chúng ta lựa chọn Function Declaration hay Function Expression.

Theo quy tắc chung, Lời khuyên là dùng cách khai báo hàm Function Declaration hơn, bởi vì chúng ta có thể gọi hàm trước khi chúng đc khai báo. Và nó cũng dễ tìm kiếm hàm f(..){...} hơn là cho f=function(...).

...Nhưng nếu Function Declaration không phù hợp, vì một số lý do nào đó. Thì ta nghĩ đến biểu thưc function (Function Express)

Arrow function

Một cú pháp rất đơn giản để tạo hàm, thường tốt hơn các biểu thức hàm. Nó được gọi là arrow function "hàm mũi tên".

let func = (arg1, arg2, ...argN) => expression

Code ở trên đã tạo một function tên là func, nó có các đối số đó là arg1... agrN, Và phần bên phải sẽ được thực hiện và trả về kết quả của nó.

Nói cách khác, nó cũng giống như code sau:

let func = function(arg1, arg2, ...argN) {
  return expression;
};

Nhưng ngắn gọn hơn nhiều:

Hãy nhìn ví dụ dưới đây

let sum = (a, b) => a + b;

alert( sum(1, 2) ); // 3

Thậm chí, nêu chúng ta chỉ có một đối số, thì dấu ngoặc đơn có thể được bỏ, rất ngắn gọn


// let double = function(n) { return n * 2 }
let double = n => n * 2;

alert( double(3) ); // 6

Nhưng nếu trong trường hợp không có tham số nào, thì tham số sẽ để trống (nhưng vẫn phải giữ nguyên dấu ngoặc)

let sayHi = () => alert("Hello!");

sayHi();

Arrow function cũng được dùng tương tự cách dùng cho biểu thức gán Function Expression.

Xem ví dụ dưới đây:

let age = prompt("What is your age?", 18);

let welcome = (age < 18) ?
  () => alert('Hello') :
  () => alert("Greetings!");

welcome(); // ok now

Cấu trúc mũi tên có thể khó đọc , khó hiểu thời gian đầu, nhưng sẽ nhanh chóng thay đổi cái nhìn khi mắt đã làm quen được.

Điều này rất thuật tiện khi viết những function đơn giản, và khi ta đã quá lười viết nhiều

Mũi tên đa cấp

Các ví dụ trên đều lấy tham số từ bên trái mũi tên, và thực hiện biểu thức bên phải.

Nhưng đôi khi chúng ta cần một thứ gì đó phức tạp hơn, nhiều câu lệnh hơn. Điều này là có thể , nhưng chúng ta nên đặt chúng trong dấu ngoặc nhọn, và cuối cùng viết return.

như sau:

let sum = (a, b) => {  // trong ngoặc là nhiều câu lệnh khác nhau
  let result = a + b;
  return result; // cuối cùng dùng lệnh return để trả về kết quả
};

alert( sum(1, 2) ); // 3

Thên nữa:

Chúng ta đã thấy được sự ngắn gọn của mũi tên function, nhưng đó không phải là tất cả. Mũi tên function còn có nhiều tính năng hay ho nữa. Chúng ta sẽ quay lại ở chương arrow function chi tiết.

Tổng kết:

  • Function là một giá trị. Chúng có thể gán, coppied hoặc khai báo tại bất kỳ nơi nào trong code
  • Nếu function được khai báo như là một câu lệnh riêng biệt trong phần code, thì đó được gọi là "Function Declaration".
  • Nếu function được tạo ra giống như là một phần của biểu thức, nó được gọi là "Function Expression".
  • Function Declaration được xử lý trước khi code bên trong được thực thi. Chúng có thể được nhìn, gọi tại bất cứ đâu.
  • Function Expression được tạo ra khi một sự thực hiện nào đó nhắc đến chúng.

Trong hầu hết các trường hợp chúng ta cần khai báo một function, thì Function Declaration được yêu thích hơn. Bởi vì nó linh hoạt hơn trong việc tổ chức code, và dễ đọc hơn.

Vậy  nên chỉ sử dụng functiopn Expression khi nào mà function Declaration không phù hợp với nhiệm vụ.

Arrow function sẽ giải quyết dễ dàng cho việc code 1 dòng. Và chúng có 2 loại như sau:

  1. Nếu không có dấu ngoặc nhọn (...args) => expression. Bên phải là sự diễn ta. Gía trị của function là trả về một kết quả
  2. Có dấu ngoặc nhọn : (...args) => { body} - Ở bên trong cho phép chúng ta viết nhiều code, nhiều dòng, nhiều lệnh, nhueng lưu ý là cuối cùng vẫn cần return lại một kết quả nào đó.

Phần tiếp theo chúng ta sẽ tìm hiểu một số phần đặc biệt trong Javascript.