Почему закрытие важно для JavaScript?


16

Лямбда-выражение C # также имеет замыкания, но редко обсуждается сообществами или книгами C #. Я вижу гораздо больше людей и книг о JavaScript, которые говорят о его закрытии, чем в мире C #. Это почему?


3
Поскольку JavaScript рассматривается как функциональный язык первого класса, а C # является классическим языком ООП. Разные парадигмы, разные стили программирования.
Рэйнос

1
Наличие функции первого класса делает язык функциональным языком. PHP (начиная с 5.3), Python или D имеет функцию первого класса. Вы бы сказали, что это функциональные языки? Конечно, нет, и JavaScript тоже.
deadalnix

1
@deadalnix JavaScript - это мультипарадигмальный язык. Он в основном поддерживает процедурную, функциональную и прототипную парадигму ОО. Это ни в коем случае не чисто функциональный язык, но вы можете легко написать javascript в функциональной парадигме без изменения языка. Я бы сказал то же самое о C # и Python.
Рейнос

3
@deadalnix, язык, который позволяет вам определять Y-комбинатор, является функциональным языком. По определению.
SK-logic

1
@deadalnix: Я полагаю, что вопрос сводится к тому, какие подходы продвигаются языком. Существует много платформ и платформ JavaScript (в частности, node.js и DOM (модель событий)), которые в значительной степени зависят от функций первого порядка. PHP имеет функции, которые допускают тот же стиль программирования, но если вы посмотрите на стандартный API или многие фреймворки, то увидите, что он не является ядром языка.
back2dos

Ответы:


5

Потому что у javascript нет таких функций, как пространства имен, и вы можете легко испортить все виды глобальных объектов.

Поэтому важно иметь возможность изолировать некоторый код в его собственной среде выполнения. Закрытие идеально подходит для этого.

Такое использование замыкания не имеет смысла в языке, подобном C #, где у вас есть пространства имен, классы и т. Д., Чтобы изолировать код и не помещать все в глобальную область видимости.

Очень распространенная практика для кода javascript - это писать так:

(function(){
    // Some code
})();

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

Javascript - это совершенно другой язык, чем C #. Он не объектно-ориентированный, он ориентирован на прототип. Это приводит к очень различным практикам в конце.

В любом случае замыкания хороши, так что используйте их даже в C #!

РЕДАКТИРОВАТЬ: После некоторого обсуждения чата stackoverflow, я думаю, что этот ответ должен быть точным.

Функция в примере кода не является замыканием. Однако эта функция может определять локальные переменные и вложенные функции. Все вложенные функции, которые используют эти локальные переменные, являются замыканиями.

Это полезно для совместного использования некоторых данных в наборе функций без нарушения глобальной области видимости. Это наиболее распространенное использование замыкания в JavaScript.

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

С закрытием вы можете сделать гораздо больше, чем просто защитить глобальную область, но это то, что вы увидите в исходном коде JS.


9
Это не закрытие. Вы описываете преимущества использования функций для создания локальной области видимости.
Райнос

2
замыкание - это только замыкание, если оно закрывается по свободным переменным. Также спасибо, что
сказали

2
вместо того чтобы прибегать к подрыву меня, называя меня новичком, не стесняйтесь выдвигать реальные аргументы в чате JavaScript SO . Это обсуждение на самом деле не относится, но я с радостью расскажу о ваших заблуждениях в SO чате.
Рейнос

1
Downvoted. JavaScript достаточно объектно-ориентирован. Это просто не на основе классов, но такая функциональность легко создается. Он имеет первоклассные функции, использует преимущества замыканий, чтобы сделать его естественным образом подходящим для парадигм, основанных на событиях, и основным источником вдохновения, по словам его автора, Брендана Эйха, была Схема. Я не совсем уверен, что вы думаете о функциональном языке, но забавная часть заключается в том, что вы, кажется, думаете, что наследование на основе классов является чем-то критическим, а не более чем необходимым, когда вы можете передавать функции и применять их в новых контекстах.
Эрик Реппен

2
-1 также. Это не описывает замыкания, оно описывает область действия.
Изката

12

Возможно, потому что популярные реализации объектной ориентации 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.


3
-1 «зависит от замыканий» Это очень субъективно. Это не.
Рейнос

Raynos: хотите показать нам, как создавать и использовать частные члены без замыканий?
user281377 30.06.11

1
@ammoQ в JavaScript нет такого понятия, как приватность. Вы имели в виду «потому что классическая эмуляция ОО JavaScript зависит от замыканий». JavaScript OO является прототипом, который представляет собой другую парадигму. Это хороший ответ на вопрос: «Мы используем замыкания в JavaScript, потому что нужно было эмулировать классическое ОО»
Raynos

1
@keppla Я имел в виду "ОО зависит от замыканий", это субъективно. Вам не нужны закрытия для ОО вообще.
Рэйнос

2
ты выставляешь меня как репу, шлюха я ...
user281377

4

Потому что многие из библиотек, которые делают JavaScript «терпимым», используют их.

Взгляните на JQuery , Prototype или MooTools , просто чтобы назвать три популярных. Каждая из этих библиотек предоставляет eachметод для своих коллекций в качестве предпочтительного способа итерации, который использует функцию итератора. Эта функция при доступе к значениям во внешней области будет закрыта:

[1,2,3].each(function(item) {
   console.log(item);
});

И это не останавливается на достигнутом: обратные вызовы в Ajax, обработка событий в Ext.js и т. Д. Все принимают функции, и если вы не хотите наполнять свой код сотнями функций, которые вызываются ровно один раз, замыкания - это путь.


1
Почему это не закрытие? console.logопределяется во внешней области видимости, consoleкак и «свободная переменная». И почему, по сути, цикл for, который ничем не отличается, плохая практика?
Кеппла

@Raynos: мое определение замыкания - «блок, содержащий свободную переменную», он не теряет этот статус, а свободная переменная находится в верхней области видимости. Но, чтобы поддержать мою точку зрения, рассмотрим этот метод: pastie.org/2144689 . Почему это должно быть плохо?
Кеппла

Я все еще думаю, что "закрытие" по глобальным данным считается обманом. Я согласен с тем, что доступ к данным в цепочке областей действия - это хорошо, просто рекомендуется минимизировать этот доступ.
Райнос

Договорились о минимальном доступе
keppla

Следует отметить, что с помощью итераторов массива (forEach, map, Reduce и т. Д.) Для них нет нулевой причины быть замыканиями, у них все состояние передается в них напрямую. Я бы посчитал анти-паттерном для них замыкания
Рейнос

3

Я согласен с другими ответами, что «хорошее» кодирование с помощью JavaScript в большей степени зависит от замыканий. Однако, в дополнение к этому, это, вероятно, просто вопрос того, как давно эта функция существует на каждом языке. JavaScript в основном имел замыкания с самых ранних реализаций. C #, с другой стороны, имел их только с версии 3.0, которая была выпущена в Visual Studio 2008.

Многие программисты на C #, с которыми я сталкиваюсь, все еще работают над проектами 2.0. И даже если они работают в 3.0 или 4.0, они часто все еще используют идиомы 2.0. Я люблю замыкания; надеюсь, они будут более активно использоваться в C #, поскольку эта концепция распространяется среди разработчиков C #.


2

Основная причина в том, что C # статически типизирован, а функции имеют доступ только к единственной, заранее определенной среде, что препятствует полезности замыканий.

В JavaScript, с другой стороны, замыкания позволяют функциям вести себя как методы, когда к ним обращаются как к свойству объекта и как к объектам первого класса, их также можно вводить в разные среды, что позволяет подпрограммам работать в разных контекстах.


1
При чем тут статическая типизация? Закрытия ортогональны.

-1

Одна из причин, по которой мне пришлось узнать о них, заключается в том, что когда вы просматриваете элементы DOM (или что-то еще), вы хотите иметь возможность «закрывать» или «инкапсулировать» область видимости переменной. Как и в примере, размещенном здесь: /programming/5606059/how-to-create-closure-in-loop-and-store-it-in-variable-for-later-execution

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.