Biểu thức của hàm

Biểu thức hàm là các hàm được tạo trong đó một biểu thức được mong đợi. Bạn sẽ thường xuyên gặp biểu thức hàm dưới dạng giá trị được chỉ định cho một biến. Mặc dù khai báo hàm luôn yêu cầu tên, bạn có thể sử dụng biểu thức hàm để tạo ẩn danh bằng cách bỏ qua giá trị nhận dạng và theo sau từ khoá function kèm theo cặp dấu ngoặc đơn chứa tham số không bắt buộc:

const myVariable = function() { };

Sau đó, bạn có thể gọi các biểu thức hàm đó bằng cách sử dụng giá trị nhận dạng của biến:

const myVariable = function() {
    console.log( "This is my function." );
};

myVariable();
> "This is my function."

Bạn cũng có thể sử dụng biểu thức hàm để tạo hàm được đặt tên bằng cú pháp tương tự như khai báo hàm:

const myVariable = function myFunction() {
    console.log( "This is my function." );
};

myVariable();
> "This is my function."

Tuy nhiên, không giống như khai báo hàm, biểu thức hàm được đặt tên có thể được truy cập theo tên hàm chỉ trong chính hàm đó:

const myVariable = function myFunction() {
  console.log( `I'm a ${ typeof myFunction }.`);
};

typeof myFunction;
> "undefined"

typeof myVariable;
> "function"

myVariable();
> "I'm a function."

Các tên được liên kết với biểu thức hàm chủ yếu hữu ích cho việc gỡ lỗi. Đáp được đặt tên cũng có thể gọi chính nó theo cách đệ quy, mặc dù đây không phải là một trường hợp sử dụng rất phổ biến trong quá trình phát triển hiện đại:

const myVariable = function myFunction() {
    console.log( "One second elapsed." );
    setTimeout( myFunction, 1000 );
};

setTimeout( myVariable, 1000 );
> "One second elapsed."
> "One second elapsed."
> "One second elapsed."

Biểu thức hàm mũi tên

Biểu thức hàm mũi tên (thường được gọi là "hàm mũi tên" hoặc hiếm khi là "lambda") hàm") được giới thiệu trong ES6 để cung cấp cú pháp ngắn gọn cho việc tạo biểu thức hàm ẩn danh với một số hành vi riêng biệt.

Bạn có thể tạo hàm mũi tên ở bất cứ nơi nào dự kiến có biểu thức, cho ví dụ như giá trị được gán cho biến. Trong hình thức phổ biến nhất, mũi tên hàm được tạo thành từ một cặp dấu ngoặc đơn phù hợp có chứa số không hoặc nhiều hơn tham số, mũi tên được tạo thành từ một dấu bằng và ký tự lớn hơn (=>) và một cặp dấu ngoặc nhọn phù hợp chứa nội dung hàm:

const myFunction = () => {};

Trong một số điều kiện, bạn có thể thu gọn cú pháp hơn nữa. Nếu bạn chỉ sử dụng một tham số, bạn có thể bỏ dấu ngoặc đơn bắt đầu:

const myFunction = myParameter => {};

Khi bạn muốn phần nội dung của hàm trả về giá trị của một biểu thức, bạn không bắt buộc phải bao gồm phần nội dung của hàm trong dấu ngoặc nhọn hoặc từ khoá return:

const myFunction = () => 2 + 2

myFunction()
> 4

Các hàm mũi tên khác biệt ở chỗ chúng không có bối cảnh riêng arguments hoặc this. Thay vào đó, chúng kế thừa cả hai các giá trị trong hàm mũi tên môi trường bao quanh từ vựng, môi trường gần nhất hàm bao gồm cung cấp các ngữ cảnh đó.

function myParentFunction() {
    this.myProperty = true;
    let myFunction = () => {
            console.log( this );
    }
    myFunction();
};

let myInstance = new myParentFunction();
> Object { myProperty: true }

Gọi hàm mũi tên

Các hàm mũi tên không liên kết các đối số theo cách giống như các loại hàm khác. Đối tượng arguments trong phần nội dung của hàm mũi tên kế thừa giá trị của đối tượng đó từ môi trường bao quanh ngữ nghĩa gần nhất của hàm mũi tên đó:

function myFunction() {
    let myArrowFunction = () => {
            console.log( arguments[ 0 ] );
    }
    myArrowFunction( true );
};

myFunction( false );
> false

Trong ví dụ này, một hàm bên ngoài được gọi với đối số false sẽ gọi một hàm mũi tên trong có đối số true. Vì đối tượng arguments bên trong hàm mũi tên phân giải thành liên kết ở hàm bên ngoài, hàm bên trong ghi lại false của hàm bên ngoài.

Nếu không có đối tượng arguments nào để kế thừa từ ngữ cảnh gốc, hãy dùng mũi tên đối tượng arguments của hàm không được xác định và việc cố gắng truy cập vào đối tượng đó sẽ gây ra lỗi:

let myArrowFunction = () => {
    console.log(arguments);
};
myArrowFunction( true );
> Uncaught ReferenceError: arguments is not defined

Biểu thức hàm được gọi ngay (IIFE)

Biểu thức hàm được gọi ngay (IIFE), đôi khi còn được gọi là "chức năng ẩn danh tự thực thi" là một biểu thức hàm được gọi ngay khi được xác định. IIFE sử dụng biểu thức hàm được tạo bởi chứa hàm trong một toán tử nhóm. Sau đó, một cặp dấu ngoặc đơn thứ hai được so khớp sẽ gọi hàm, ngay sau định nghĩa hàm hoặc ngay sau toán tử nhóm. Nếu bạn sử dụng một hàm chuẩn, thì sẽ không có gì khác biệt trên thực tế giữa 2 phương pháp:

(function() {
    console.log( "IIFE.")
    }
)();
> "IIFE."

(function() {
    console.log( "IIFE.")
    }
());
> "IIFE."

Ví dụ đầu tiên gọi biểu thức hàm được nhóm. Ví dụ thứ hai gọi một phần khai báo hàm bên trong các toán tử nhóm và kết quả cuối cùng sau đó được đánh giá dưới dạng một biểu thức đã nhóm. Kết quả giống nhau trong trường hợp.

Tuy nhiên, sẽ có sự khác biệt khi IIFE là hàm mũi tên. Trong phần này chữ hoa, dấu ngoặc đơn dùng để gọi hàm phải nằm ngoài nhóm các toán tử, vì bản thân hàm mũi tên không phải là một biểu thức mà phải được tạo trong ngữ cảnh trong đó một biểu thức được mong đợi. Việc cố gắng gọi hàm mũi tên từ bên trong phạm vi của các toán tử nhóm có nghĩa là gọi một hàm mũi tên chưa được tạo trong ngữ cảnh của một biểu thức:

( () => {
    console.log( "IIFE." );
}() );
> Uncaught SyntaxError: missing ) in parenthetical

Vì các toán tử nhóm mong đợi có một biểu thức, nên hàm mũi tên trong chúng được xác định, cho phép các dấu ngoặc đơn theo sau gọi hàm được nhóm biểu thức:

( () => {
    console.log( "IIFE." );
} )();
> "IIFE."

Các ứng dụng cũ, IIFE thường xuyên được sử dụng để quản lý phạm vi, đặc biệt là tránh làm ô nhiễm phạm vi toàn cầu thông qua các biến ở phạm vi hàmkhai báo hàm. Trước khi giới thiệu tính năng phạm vi khối trong ES6, người ta thường gói toàn bộ tập lệnh trong IIFE để ngăn chặn ô nhiễm không chủ ý trong phạm vi toàn cầu.

Kiểm tra kiến thức

Bạn có thể gọi biểu thức hàm được đặt tên theo tên bên ngoài không?

Không