Hàm

Hàm là một khối câu lệnh theo mô-đun, có thể tái sử dụng, dùng để thực hiện một tập hợp các tác vụ liên quan, chẳng hạn như tính toán và trả về một giá trị dựa trên các đối số được cung cấp cho hàm. Giống như tất cả các giá trị không phải là giá trị gốc, hàm đều là các đối tượng. Đây là các đối tượng duy nhất mà chúng có thể được gọi để thực thi mã, được chuyển dữ liệu ở dạng đối sốreturn một giá trị.

Hàm được coi là đối tượng "lớp thứ nhất", nghĩa là mặc dù có hành vi riêng biệt, chúng vẫn có thể được sử dụng trong mọi ngữ cảnh tương tự như mọi đối tượng JavaScript khác. Ví dụ: một hàm có thể được chỉ định cho một biến, truyền dưới dạng đối số cho các hàm khác và được các hàm khác trả về.

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

Hàm được xác định là thuộc tính của một đối tượng thường được gọi là "phương thức". Tương tự như với các biến được khai báo bằng var`, nội dung khai báo hàm được thực hiện bên ngoài một hàm bao hàm sẽ được thêm vào đối tượng chung dưới dạng phương thức.

Khai báo hàm

Phần khai báo hàm (còn gọi là "câu lệnh hàm" hoặc "định nghĩa hàm") tạo một hàm được đặt tên có thể được gọi ở nơi khác trong phạm vi chứa hàm. Nội dung khai báo hàm bao gồm từ khoá function, theo sau là giá trị nhận dạng, danh sách các tham số được phân tách bằng dấu phẩy đặt trong dấu ngoặc đơn và câu lệnh khối được gọi là "nội dung hàm". Bạn sẽ thường xuyên gặp các nội dung khai báo hàm không kết thúc bằng dấu chấm phẩy; vì khai báo hàm là một câu lệnh, nên dấu chấm phẩy theo sau có thể được dự đoán bằng ASI.

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

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

Để nắm quyền kiểm soát các quyết định thiết kế ban đầu của JavaScript, nội dung khai báo hàm phải tuân theo cùng hành vi chuyển lên trên (hoisting) cũ như các biến được khai báo bằng var, nghĩa là nội dung khai báo hàm được chuyển lên đầu phạm vi và có thể được gọi trước khi khai báo kết quả, cho dù phạm vi đó có chịu sự điều chỉnh của chế độ nghiêm ngặt hay không:

"use strict";
{
    myFunction();
    function myFunction() {
        console.log( "This is my function." );
    };
}
> "This is my function."

Ngoài chế độ nghiêm ngặt, phần khai báo hàm sẽ sử dụng hành vi phạm vi cũ của JavaScript, nghĩa là nội dung khai báo hàm nằm trong phạm vi hàm bao bọc gần nhất:

function myFunction() {
    function myNestedFunction() {
        console.log( "This is my nested function." );
    }
    myNestedFunction();
};

myFunction();
> "This is my nested function."

myNestedFunction();
>Uncaught ReferenceError: myNestedFunction is not defined

chế độ nghiêm ngặt, các nội dung khai báo hàm sẽ nằm trong phạm vi của khối bao bọc gần nhất, giống như với các biến được khai báo bằng let hoặc const:

"use strict";
{
    function myFunction() {
        console.log( "This is my function." );
    };
}

myFunction();
> Uncaught ReferenceError: myFunction is not defined

Gọi hàm

Giống như biến, giá trị nhận dạng được dùng khi khai báo hàm đóng vai trò là tên tượng trưng cho một giá trị. Việc tham chiếu một hàm theo giá trị nhận dạng chỉ trả về đối tượng hàm và không thực thi hàm trong đó:

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

myFunction;
> myFunction() {
   console.log( "This is my function." );
}

Để thực thi mã bên trong phần nội dung hàm, hãy gọi (hoặc gọi) hàm bằng cách theo sau tên hàm với một cặp dấu ngoặc đơn phù hợp:

function myFunction() {
    console.log( "My function has been executed." );
}

myFunction();
> "My function has been executed."

Các tham số trong định nghĩa hàm đóng vai trò là biến phần giữ chỗ cho các giá trị có thể được truyền vào phần nội dung hàm khi hàm được gọi. Các giá trị trong dấu ngoặc đơn khi một hàm được gọi là "đối số" (mặc dù bạn có thể thấy "đối số" dùng để mô tả cả đối số và tham số trong một số tài liệu):

function myFunction( myParameter ) {
   console.log( `The value is: ${ myParameter }.` );
};

myFunction( "this string" );
> "The value is: this string."

Nếu một đối số dự kiến bị bỏ qua, thì tham số thu được sẽ chứa giá trị undefined vì tham số đó được khai báo cho phần nội dung hàm nhưng không được khởi tạo bằng một giá trị:

function myFunction( myParameter ) {
   console.log( `The value is: ${ myParameter }.` );
};

myFunction();
> "The value is: undefined."

Bạn có thể đặt giá trị tham số mặc định bằng cách khởi chạy các giá trị này giống như cách bạn khởi tạo biến: toán tử chỉ định (=) theo sau là một giá trị. Nếu sau này bạn chỉ định một đối số cho hàm đó, thì giá trị mới đó sẽ ghi đè giá trị mặc định:

function myFunction( myParameter = "omitted" ) {
   console.log( `The value is: ${ myParameter }.` );
};

myFunction( "this string" );
> "The value is: this string."

myFunction();
> "The value is: omitted."

Phần thân của hàm không mũi tên cũng có quyền truy cập vào đối tượng arguments giống như mảng được lập chỉ mục bằng 0 chứa bất kỳ giá trị nào được truyền dưới dạng đối số, cho dù định nghĩa hàm có chỉ định các tham số hay không:

function myFunction() {
   console.log( arguments );
};

myFunction( 3, true, "My string" );
> Arguments { 0: 3, 1: true, 2: "My string", … }

Hàm Variadic

Đối tượng arguments cho phép bạn tạo hàm biến thiên cơ bản. Hàm này có thể chấp nhận số lượng đối số có thể thay đổi:

function myFunction() {
    let result = "";
    for (let i = 0; i < arguments.length; i++) {
        result += arguments[i] + " - ";
    }
    console.log( result );
};

myFunction( "My first string", "My second string", "my third string" );\
> "My first string - My second string - my third string - "

Tuy nhiên, phương pháp này đối với các hàm biến đổi hiếm khi được sử dụng trong quá trình phát triển JavaScript hiện đại. Thông thường, bạn nên sử dụng cú pháp tham số còn lại hiện đại và dễ đọc hơn. Thao tác này sẽ tạo một tham số có tên được khởi tạo dưới dạng một mảng chứa mọi đối số ngoài các đối số được chỉ định rõ ràng:

function myFunction( mySeparator, ...myStrings ) {
  console.log( myStrings.join( mySeparator ) );
};

myFunction( " - ", "My first string", "My second string", "my third string" );
> "My first string - My second string - my third string"

Không giống như liên kết parameter, cú pháp tham số nghỉ hoạt động như dự kiến với các tham số hàm mũi tên:

function myOuterFunction() {
    let myInnerArrowFunction = ( ...myParams ) => {
        console.log( myParams[ 0 ] );
    }
    myInnerArrowFunction( true );
};

myOuterFunction( false );
> true

let myArrowFunction = ( ...myParams ) => {
    console.log( myParams[ 0 ] );
};

myArrowFunction( true );
> true`
``