Инкапсуляция — это упаковка данных функциями, которые позволяют работать с этими данными. Это основа ООП (объектно-ориентированного программирования) и используется с объектно-ориентированными языками, такими как Java или C#, чтобы скрыть или ограничить доступ/использование вашего структурированного объекта, чтобы вы могли контролировать его состояние.

Ну, JavaScript не является объектно-ориентированным языком, но мы хотим обойти хорошие стороны ООП, поэтому мы можем применить инкапсуляцию к структурированному экземпляру с помощью широко используемой практики с IIFE (немедленно вызываемое функциональное выражение) и раскрывающий модуль шаблон.

IIFE

Немедленно вызываемое функциональное выражение — это, по сути, функция в лексической области видимости, но вы комбинируете ее с функциональным выражением (), поэтому движок JavaScript напрямую интерпретирует функцию, когда она определена, а внутренние операторы недоступны извне.

(function(){
var myStore = [“Apple”, "Banana", "Mango", "Orange"]
})();
console.log("myStore is", myStore); 
// returns error: ReferenceError: myStore is not defined

Вы можете получить доступ к его внутреннему оператору, только присвоив возвращаемое значение IIFE переменной:

const store = (function () {
var myStore = [“Apple”, “Banana”, “Mango”, “Orange”];
return myStore;
})();
console.log(“myStore is”, store);
//myStore is [ 'Apple', 'Banana', 'Mango', 'Orange' ]

Поскольку мы стремимся применить концепцию инкапсуляции, давайте просто рассмотрим улучшенную версию этого примера магазина с основными функциями, которые могут быть у нас в реальной жизни.

Выявление шаблона модуля

Модули — наиболее часто используемые шаблоны проектирования в JavaScript. Он обеспечивает слабую связь, чтобы иметь хорошо структурированный код. Поскольку IIFE предоставляет частные операторы области видимости, когда мы используем его с этим шаблоном, у нас будут хорошо спроектированные инкапсулированные объекты.

Вы можете видеть, как я разработал код выше с помощью этого шаблона:

const store = (() => {
    /**
     * private members => only private to constructor function scope
     */
    const _store = ["Apple", "Banana", "Mango", "Orange"];
    const _print = (data) => {
        console.log("Inventory: ", data.toString());
    }
    /**
     * public members
     */
    return {
        getInventory: () => _print(_store),
    }
})();
store.getInventory();
Returns Inventory:  Apple,Banana,Mango,Orange

Примечание. Я также использую выражение стрелочной функции

Давайте изменим его больше:

const store = (() => {
    /**
     * private members => only private to constructor function scope
     */
    const _store = ["Apple", "Banana", "Mango", "Orange"];
    const _print = (data) => {
        console.log("Inventory: ", data.toString());
    }
    const _addOne = (item) => {
        _store.push(item);
    }
    /**
     * public members
     */
    return {
        getInventory: () => _print(_store),
        addInventory: (item) => _addOne(item),
    }
})();
store.addInventory("Cherry");
store.getInventory();
Returns Inventory:  Apple,Banana,Mango,Orange,Cherry

… и проверьте, как на самом деле отображается функция store:

console.log("Store: ", store);
Returns
Store:  {
  getInventory: [Function: getInventory],
  addInventory: [Function: addInventory]
}

RMP позволяет store IIFE успешно инкапсулировать свои частные члены или состояние и позволяет только общедоступным членам получать доступ или работать с состоянием.

Спасибо за чтение!