+8

PEAN Stack Day 1 - IIFE, Scope và Closure

Mở đầu series mới về PEAN stack, mình sẽ cùng các bạn tìm hiểu 3 khái niệm hay ho trong Javascript: IIFE, Scope, và Closure. Đây là những khái niệm mà mình tin rằng mọi javascript developer cần nắm vững!

1. IIFE - Immediately Invoked Function Expressions

1.1. Khái niệm

Các bạn đã bao giờ tự hỏi, làm cách nào tạo một function và tự động thực thi nó ngay lập tức không? Đó chính là IIFE!

IIFE là cách mà chúng ta có thể tạo một function và chạy nó ngay lập tức mà không cần gọi tên function đó.

Ví dụ:

(function() {
    console.log("Đây là IIFE!"); // Đây là IIFE!
})();

1.2. Ứng dụng

Một ứng dụng thực sự hữu ích của IIFE là giúp chúng ta tạo ra "private variables" trong Javascript. Với IIFE, biến bên trong function sẽ không bị ảnh hưởng bởi các biến bên ngoài.

Ví dụ:

var name = "IT VN Chất";

(function() {
    var name = "Private World!";
    console.log(name); // Private World!
})();

console.log(name); // IT VN Chất

2. Scope

2.1. Khái niệm

Scope giúp chúng ta kiểm soát và quản lý phạm vi hoạt động của biến. Trong Javascript, chúng ta có 2 loại scope chính là: Global ScopeLocal Scope.

2.2. Ứng dụng

  • Global Scope: Khi một biến được khai báo bên ngoài function.

    var globalVar = "Tôi là global!";
    
    function checkScope() {
        console.log(globalVar); // Tôi là global!
    }
    
    checkScope();
    
  • Local Scope: Khi một biến được khai báo bên trong function.

    function checkScope() {
        var localVar = "Tôi là local!";
        console.log(localVar); // Tôi là local!
    }
    
    checkScope();
    console.log(localVar); // Error: localVar is not defined
    

3. Closure

3.1. Khái niệm

Closure là một function được tạo ra bởi một function khác. Đặc điểm nổi bật là closure có thể truy cập vào các biến của function cha của nó.

3.2. Ứng dụng

Closure giúp chúng ta tạo ra các private methods hay variables trong Javascript.

Ví dụ:

function makeCounter() {
    var count = 0;
    
    return function() {
        return count++;
    };
}

var counter = makeCounter();

console.log(counter()); // 0
console.log(counter()); // 1

Trong ví dụ trên, function bên trong truy cập và tăng biến count mặc dù nó được định nghĩa ngoài cùng. Điều này chỉ có thể xảy ra nhờ Closure.

Một số ví dụ khác

IIFE (Immediately Invoked Function Expressions)

Ví dụ 1: Sử dụng IIFE để khởi tạo một plugin

Giả sử bạn đang viết một plugin jQuery và muốn đảm bảo không ảnh hưởng tới các biến hoặc hàm ngoài.

(function($) {
    // Bên trong đây, $ sẽ là jQuery
    $(document).ready(function() {
        // Mã của plugin
    });
})(jQuery);

Ở đây, chúng ta sử dụng IIFE để tránh xung đột giữa jQuery và các thư viện khác. $ bên trong IIFE sẽ luôn ám chỉ jQuery.

Ví dụ 2: Khởi tạo một biến chỉ đọc

var CONSTANTS = (function() {
    var secretKey = "12345";
    return {
        API_URL: "https://myapi.com",
        getSecretKey: function() {
            return secretKey;
        }
    };
})();

console.log(CONSTANTS.API_URL); // https://myapi.com
console.log(CONSTANTS.getSecretKey()); // 12345

Trong ví dụ này, IIFE giúp tạo ra một object CONSTANTS mà người dùng chỉ có thể truy cập thông qua các phương thức được cung cấp.

Scope

Ví dụ 1: Sử dụng block scope để xử lý dữ liệu

{
    let temporaryData = "data";
    // Xử lý temporaryData
    console.log(temporaryData); // "data"
}

//console.log(temporaryData); // Lỗi: temporaryData không tồn tại

Ở ví dụ này, temporaryData chỉ tồn tại trong block {}, giúp tránh làm ô nhiễm global scope.

Ví dụ 2: Sử dụng function scope để tạo biến riêng biệt

function processData(data) {
    var processed = "Processed: " + data;
    return processed;
}

console.log(processData("myData")); // Processed: myData
//console.log(processed); // Lỗi: processed không tồn tại

Ở đây, biến processed chỉ tồn tại trong hàm processData, giúp tách biệt logic xử lý.

Closure

Ví dụ 1: Tạo một hàm tăng giá trị

function createIncrementer() {
    let count = 0;
    return function() {
        return count++;
    };
}

const increment = createIncrementer();

console.log(increment()); // 0
console.log(increment()); // 1

Hàm createIncrementer trả về một closure giữ lại trạng thái của count mỗi khi gọi hàm increment.

Ví dụ 2: Ẩn dữ liệu bên trong một module

var Module = (function() {
    var privateData = "I am private";

    return {
        getPrivateData: function() {
            return privateData;
        }
    };
})();

console.log(Module.getPrivateData()); // "I am private"
//console.log(Module.privateData); // undefined

Sử dụng closure, chúng ta có thể tạo ra các module với dữ liệu và phương thức riêng tư. Trong ví dụ trên, privateData chỉ có thể truy cập thông qua hàm getPrivateData.


English version

Hey there! Let's dive into a new series about the PEAN stack. Today, we'll explore three cool ideas in JavaScript: IIFE, Scope, and Closure. These are concepts that I believe every JavaScript developer should get a good grasp on.

1. IIFE - Immediately Invoked Function Expressions

1.1. What's this?

Have you ever wondered how to create a function and make it run right away without calling its name? Well, that's where IIFE comes in!

IIFE is a way to create a function and run it immediately without needing to call its name.

For example:

(function() {
    console.log("This is an IIFE!"); // This is an IIFE!
})();

1.2. Where it shines

One super useful thing about IIFE is that it helps us make "private variables" in JavaScript. With IIFE, variables inside the function won't be affected by variables outside of it.

For instance:

var name = "Awesome IT World";

(function() {
    var name = "Private Galaxy!";
    console.log(name); // Private Galaxy!
})();

console.log(name); // Awesome IT World

2. Scope

2.1. Scope? What's that?

Scope helps us control and manage where variables work. In JavaScript, we have two main types of scope: Global Scope and Local Scope.

2.2. Where to use them

  • Global Scope: When a variable is declared outside a function.

    var globalVar = "I am global!";
    
    function checkScope() {
        console.log(globalVar); // I am global!
    }
    
    checkScope();
    
  • Local Scope: When a variable is declared inside a function.

    function checkScope() {
        var localVar = "I am local!";
        console.log(localVar); // I am local!
    }
    
    checkScope();
    console.log(localVar); // Error: localVar is not defined
    

3. Closure

3.1. What's Closure?

Closure is a function that's created by another function. The special thing about closure is that it can access variables from its parent function.

3.2. Where's it handy?

Closure helps us make private methods or variables in JavaScript.

For example:

function makeCounter() {
    var count = 0;
    
    return function() {
        return count++;
    };
}

var counter = makeCounter();

console.log(counter()); // 0
console.log(counter()); // 1

In this example, the inner function accesses and increases the count variable even though it's defined outside. This magic happens thanks to Closure.

Some more examples

IIFE (Immediately Invoked Function Expressions)

Example 1: Using IIFE to set up a plugin

Let's say you're crafting a jQuery plugin and want to make sure it doesn't mess with other variables or functions.

(function($) {
    // Inside here, $ means jQuery
    $(document).ready(function() {
        // Plugin code
    });
})(jQuery);

Here, we use IIFE to prevent conflicts between jQuery and other libraries. The $ inside the IIFE always refers to jQuery.

Example 2: Creating a read-only variable

var CONSTANTS = (function() {
    var secretKey = "12345";
    return {
        API_URL: "https://myapi.com",
        getSecretKey: function() {
            return secretKey;
        }
    };
})();

console.log(CONSTANTS.API_URL); // https://myapi.com
console.log(CONSTANTS.getSecretKey()); // 12345

In this example, IIFE helps us create a CONSTANTS object that users can only access through provided methods.

Scope

Example 1: Using block scope for data handling

{
    let temporaryData = "data";
    // Handle temporaryData
    console.log(temporaryData); // "data"
}

//console.log(temporaryData); // Error: temporaryData doesn't exist

In this example, temporaryData only exists within the curly braces {}, avoiding polluting the global scope.

Example 2: Using function scope to isolate variables

function processData(data) {
    var processed = "Processed: " + data;
    return processed;
}

console.log(processData("myData")); // Processed: myData
//console.log(processed); // Error: processed doesn't exist

Here, the processed variable only exists within the processData function, keeping the processing logic separate.

Closure

Example 1: Creating an increment function

function createIncrementer() {
    let count = 0;
    return function() {
        return count++;
    };
}

const increment = createIncrementer();

console.log(increment()); // 0
console.log(increment()); // 1

The createIncrementer function returns a closure that holds onto the state of count each time increment is called.

Example 2: Hiding data inside a module

var Module = (function() {
    var privateData = "I am private";

    return {
        getPrivateData: function() {
            return privateData;
        }
    };
})();

console.log(Module.getPrivateData()); // "I am private"
//console.log(Module.privateData); // undefined

Using closure, we can create modules with private data and methods. In the example above, privateData can only be accessed through getPrivateData function.


日本語版

よし、新しいシリーズのスタートです!PEANスタックに関する新しいシリーズを始めます。今回はJavaScriptの中で興味深い3つの概念、IIFE(イーフィー)、スコープ、そしてクロージャについて一緒に学びましょう。これらの概念は、すべてのJavaScript開発者がしっかり理解しておくべきものですよ!

1. IIFE - 即時実行関数式

1.1. 概念

みんな、一度は「関数を作って、それをすぐに実行する方法ってどうやるの?」って考えたことがありますよね?それがIIFEです!

IIFE(イーフィー) とは、関数を作成し、その関数の名前を呼び出さずにすぐに実行する方法なんです。

例えば:

(function() {
    console.log("これがIIFEだよ!"); // これがIIFEだよ!
})();

1.2. 用途

IIFEの本当に役立つ用途の一つは、JavaScript内で「プライベート変数」を作成することです。IIFEを使うと、関数内の変数は外部の変数に影響を受けないようになります。

例えば:

var name = "すごいITエンジニア";

(function() {
    var name = "プライベートワールド!";
    console.log(name); // プライベートワールド!
})();

console.log(name); // すごいITエンジニア

2. スコープ

2.1. 概念

スコープは、変数の活動範囲を制御し管理するのに役立ちます。JavaScriptには、グローバルスコープローカルスコープ の2つの主要なスコープがあります。

2.2. 用途

  • グローバルスコープ: 関数の外で変数が宣言されている場合。

    var globalVar = "僕はグローバルだよ!";
    
    function checkScope() {
        console.log(globalVar); // 僕はグローバルだよ!
    }
    
    checkScope();
    
  • ローカルスコープ: 関数内で変数が宣言されている場合。

    function checkScope() {
        var localVar = "僕はローカルだよ!";
        console.log(localVar); // 僕はローカルだよ!
    }
    
    checkScope();
    console.log(localVar); // エラー:localVarは未定義です
    

3. クロージャ

3.1. 概念

クロージャ とは、他の関数から作成される関数のことです。特筆すべき特徴は、クロージャがその親関数の変数にアクセスできることです。

3.2. 用途

クロージャを使うことで、JavaScript内でプライベートメソッドや変数を作成することができます。

例えば:

function makeCounter() {
    var count = 0;
    
    return function() {
        return count++;
    };
}

var counter = makeCounter();

console.log(counter()); // 0
console.log(counter()); // 1

上記の例では、外側で定義された関数内の関数が count 変数にアクセスして増やしています。これはクロージャを使うことで可能になります。

他の例も見てみよう

IIFE(即時実行関数式)

例1:プラグインを初期化するためにIIFEを使用

jQueryのプラグインを作成しているとしましょう。外部の変数や関数に影響を与えないようにしたい場合、IIFEが役立ちます。

(function($) {
    // ここで $ は jQuery です
    $(document).ready(function() {
        // プラグインのコード
    });
})(jQuery);

ここでは、IIFEを使ってjQueryと他のライブラリとの衝突を避けています。IIFE内の $ は常にjQueryを指します。

例2:読み取り専用の変数を初期化

var CONSTANTS = (function() {
    var secretKey = "12345";
    return {
        API_URL: "https://myapi.com",
        getSecretKey: function() {
            return secretKey;
        }
    };
})();

console.log(CONSTANTS.API_URL); // https://myapi.com
console.log(CONSTANTS.getSecretKey()); // 12345

この例では、IIFEを使って CONSTANTS オブジェクトを作成し、ユーザーが提供されたメソッドを通じてのみアクセスできるようにしています。

スコープ

例1:ブロックスコープを使用してデータを処理

{
    let temporaryData = "データ";
    // temporaryDataの処理
    console.log(temporaryData); // "データ"
}

//console.log(temporaryData); // エラー:temporaryDataは存在しません

この例では、temporaryData{} ブロック内だけで存在し、グローバルスコープの混乱を防ぎます。

例2:関数スコープを使用して個別の変数を作成

function processData(data) {
    var processed = "処理済み:" + data;
    return processed;
}

console.log(processData("私のデータ")); // 処理済み:私のデータ
//console.log(processed); // エラー:processedは存在しません

ここでは、変数 processed は関数 processData 内でのみ存在し、処理ロジックを隔離するのに役立っています。

クロージャ

例1:値を増やす関数を作成

function createIncrementer() {
    let count = 0;
    return function() {
        return count++;
    };
}

const increment = createIncrementer();

console.log(increment()); // 0
console.log(increment()); // 1

関数 createIncrementer は、毎回 increment 関数を呼び出すたびに count の状態を保持するクロージャを返します。

例2:モジュール内のデータを隠蔽

var Module = (function() {
    var privateData = "私はプライベートです";

    return {
        getPrivateData: function() {
            return privateData;
        }
    };
})();

console.log(Module.getPrivateData()); // "私はプライベートです"
//console.log(Module.privateData); // 未定義

クロージャを使って、データとプライベートメソッドを持つモジュールを作成できます。上の例では、privateData には getPrivateData 関数を通じてしかアクセスできません。

Mình hy vọng bạn thích bài viết này và học thêm được điều gì đó mới.

Donate mình một ly cafe hoặc 1 cây bút bi để mình có thêm động lực cho ra nhiều bài viết hay và chất lượng hơn trong tương lai nhé. À mà nếu bạn có bất kỳ câu hỏi nào thì đừng ngại comment hoặc liên hệ mình qua: Zalo - 0374226770 hoặc Facebook. Mình xin cảm ơn.

Momo: NGUYỄN ANH TUẤN - 0374226770

TPBank: NGUYỄN ANH TUẤN - 0374226770 (hoặc 01681423001)

image.png


All Rights Reserved

Viblo
Let's register a Viblo Account to get more interesting posts.