Лямбда-вираз C # також має закриття, але рідко обговорюється спільнотами або книгами C #. Я бачу набагато більше людей і книг JavaScript говорять про його закриття, ніж вони роблять у світі C #. Чому так?
Лямбда-вираз C # також має закриття, але рідко обговорюється спільнотами або книгами C #. Я бачу набагато більше людей і книг JavaScript говорять про його закриття, ніж вони роблять у світі C #. Чому так?
Відповіді:
Оскільки у JavaScript немає такої функції, як простори імен, і ви можете легко псувати з усіма глобальними об’єктами.
Тому важливо вміти ізолювати якийсь код у власному середовищі виконання. Закриття ідеально підходить для цього.
Таке використання закриття не має сенсу для такої мови, як C #, де у вас є простори імен, класи тощо, щоб ізолювати код і не ставити все в глобальну сферу.
Дуже поширена практика коду javascript - це писати так:
(function(){
// Some code
})();
Як бачите, це анонімне оголошення функції з подальшим негайним його виконанням. Таким чином, до всього, що визначено в межах функції, неможливо отримати доступ ззовні, і ви не зіпсуєте глобальну область. Контекст виконання цієї функції залишатиметься активним до тих пір, поки якийсь код використовує його, як вкладені функції, визначені в цьому контексті, які ви можете передавати як зворотний виклик або будь-який інший.
Javascript - це зовсім інша мова, ніж C #. Він не орієнтований на об’єкти, він орієнтований на прототип. Це призводить до дуже різних практик наприкінці.
У всякому разі, закриття є гарними, тому використовуйте їх навіть у C #!
EDIT: Після деяких обговорень в чаті stackoverflow я думаю, що цю відповідь потрібно точно уточнити.
Функція у зразковому коді не є закриттям. Однак цей funntion може визначати локальну змінну та вкладені функції. Усі вкладені функції, які використовують ці локальні змінні, - це закриття.
Це корисно для обміну деякими даними через набір функцій, не псуючи глобальну сферу. Це найпоширеніше використання закриття в JavaScript.
Закриття набагато потужніше, ніж просто обмін деякими подібними даними, але давайте бути реалістичними, більшість програмістів нічого не знає про функціональне програмування. У C # ви б використовували клас або простір імен для подібного використання, але JS не забезпечує цю функціональність.
З закриттям можна зробити більше, ніж просто захистити глобальну область, але це те, що ви побачите у вихідному коді JS.
Можливо, тому, що популярні реалізації об'єктної орієнтації JavaScript залежать від закриттів. Розглянемо простий приклад:
function counter() {
var value = 0;
this.getValue = function() { return value; }
this.increase = function() { value++; }
}
var myCounter = new counter();
console.log(myCounter.getValue());
myCounter.increase();
console.log(myCounter.getValue());
Методи getValue
і increase
фактично є закриттями, інкапсулюючи змінну value
.
Тому що багато бібліотек, які роблять JavaScript 'терплячим', використовують їх.
Погляньте на JQuery , Prototype або MooTools , лише щоб назвати три популярні. Кожна з цих бібліотек надає each
метод для своїх колекцій як кращий спосіб ітерації, який використовує функцію ітератора. Ця функція при доступі до значень у зовнішній області буде закриттям:
[1,2,3].each(function(item) {
console.log(item);
});
І це на цьому не зупиняється: зворотні виклики в Ajax, обробка подій у Ext.js і т. Д. Всі беруть на себе функції, і якщо ви не хочете роздути свій код 100-ма функціями, які викликаються точно один раз, закриття - це шлях.
console.log
визначається у зовнішній області, тому console
є "вільною змінною". І чому, насправді, це цикл for-петлі, який не робить нічого іншого, погана практика?
Я погоджуюся з іншими відповідями, що "хороше" кодування JavaScript значною мірою залежить від закриття. Однак, на додаток до цього, мабуть, лише питання про те, як довго ця функція існує в кожній мові. В основному JavaScript закрився з моменту його раннього впровадження. З іншого боку, у C # вони були лише з 3.0, який вийшов разом з Visual Studio 2008.
Дуже багато програмістів на C #, з якими я стикаюся, досі працюють над проектами 2.0. І навіть якщо вони працюють у версії 3.0 або 4.0, вони часто все ще використовують ідіоми 2.0. Я люблю закриття; сподіваємось, вони стануть більш активно використовуватися в C #, коли концепція поширюється серед розробників C #.
Основна причина полягає в тому, що C # набраний статично і функції мають лише доступ до єдиного заздалегідь визначеного середовища, що перешкоджає корисності закриття.
З іншого боку, закриття дозволяє функціям функціонувати як методи, коли вони отримують доступ як властивість об'єкта і будучи об'єктами першокласного класу, вони також можуть бути введені в різні середовища, що дозволяє підпрограмам працювати в різних контекстах.
Однією з причин, що мені довелося дізнатися про них, було те, що коли ви перебираєте елементи DOM (або що-небудь справді), ви хочете мати можливість "закрити" або "інкапсулювати" змінну область. Як у прикладі, розміщеному тут: /programming/5606059/how-to-create-closure-in-loop-and-store-it-in-variable-for-later-execution