Инкапсуляция — это упаковка данных функциями, которые позволяют работать с этими данными. Это основа ООП (объектно-ориентированного программирования) и используется с объектно-ориентированными языками, такими как 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 успешно инкапсулировать свои частные члены или состояние и позволяет только общедоступным членам получать доступ или работать с состоянием.
Спасибо за чтение!