Закрытие - это сложность на языке JavaScript и его функции. Многие передовые приложения полагаются на закрытие для реализации. Я долгое время подвергался концепции закрытия, но я был смущен и не смог понять, что такое закрытие JavaScript и что они полезны. Сегодня я увидел статью о закрытии JavaScript (оригинальная ссылка) в Интернете. Это было очень хорошо объяснено. Теперь я полностью понял, что закрытие JavaScript - это волшебная вещь и цель закрытия. Я напишу их здесь, чтобы поделиться с вами. Я надеюсь, что друзья, которые не понимают закрытия JavaScript, могут понять закрытие после их прочтения! Большая часть следующего контента поступает из исходного текста. Я добавил некоторые комментарии кода, операционные визуализации и небольшую модификацию в исходном тексте для легкого понимания!
1. Объем переменных
Чтобы понять закрытие, вы должны сначала понять особую переменную варианта JavaScript.
В JavaScript объем переменных делятся на два типа: глобальные переменные и локальные переменные.
В JavaScript глобальные переменные могут быть прочитаны непосредственно внутри функции.
var n =; // Определить глобальную переменную nfunction f () {alert («Доступ к глобальной переменной n, n ="+n); // Доступ к глобальной переменной n} f (); //Результаты работы:
Но наоборот невозможно, локальные переменные внутри функции не могут быть прочитаны вне функции.
function f () {var n =; // определить локальную переменную n} alert («Доступ к локальной переменной n вне функции, n ="+n); // Доступ к локальной переменной n вне функции, ошибка: n не определенаРезультаты работы:
Здесь есть место, где нужно отметить. При провозглашении переменных внутренне вы должны использовать команду VAR. Если нет, то это на самом деле глобальная переменная, объявленная!
Функция f () {n =;} f (); alert ("n не объявляется с помощью var внутри функции F1, в настоящее время n - глобальная переменная, /r /n доказательство: n ="+n+", результат Window.n == n IS:"+(window.n == n));Результаты работы:
2. Как прочитать локальные переменные снаружи?
По разным причинам нам иногда нужно получить локальные переменные в рамках функции. Однако, как упоминалось ранее, при нормальных обстоятельствах это не может быть сделано и может быть достигнуто только с помощью обходных путей.
То есть определить другую функцию внутри функции.
function f () {var n =; // локальная переменная n внутри F -функция // Определить функцию f -функции f () {// Inside f function, alert (n); //}}В приведенном выше коде функция F2 включена внутри функции F1, а все локальные переменные внутри F1 видны для F2. Но наоборот невозможно. Локальные переменные внутри F2 невидимы для F1. Это структура «цепочка», уникальная для языка JavaScript. Дочерние объекты будут искать вверх уровнем по уровню для всех переменных родительских объектов. Следовательно, все переменные родительского объекта видны для дочернего объекта, в противном случае это не так. Поскольку F2 может читать локальные переменные в F1, если F2 используется в качестве возврата, не можем ли мы прочитать ее внутренние переменные вне F1? У некоторых людей могут быть вопросы. F2 - это функция, как его можно вернуть как возвращаемое значение функции F1? На самом деле, это нормально. Имя функции в самой JavaScript является переменной, поэтому функция также может использоваться в качестве нормальной переменной. То есть не только одна функция может быть передана в другую функцию, такую как передача параметров, но и одна функция также может быть возвращена как возвращаемое значение другой функции.
функция f () {var n =; // локальная переменная n // f Функция, объявленная внутри f -функции f () {alert (n); } return f; // Использовать f -функцию в качестве возвращаемого значения f -функции} var result = f (); // возвращаемое значение после вызываемого f является функцией f, а результат f -функции ressul (); // 999, вызов F2 ФункцияРезультаты работы:
3. Концепция закрытия
Функция F2 в предыдущем разделе кода является закрытием. Определение «закрытия» в различных профессиональных документах очень абстрактно. Например, существует определение закрытия: «Закрытие JavaScript - это переменная, которую она получает из предыдущей функции или объема уровня в другой области, и эти переменные не будут разрушены, поскольку выполнение функции предыдущего уровня завершено». Мне трудно понять такое определение закрытия. Насколько я понимаю, закрытие - это функция, которая может считывать переменные внутри других функций. Поскольку на языке JavaScript только подфункции внутри функций могут читать локальные переменные, закрытия можно просто понимать как «функции, определенные внутри функции». Итак, по сути, закрытие - это мост, соединяющий внутреннюю и внешнюю часть функции.
4. Цель закрытия
Закрытие можно использовать во многих местах. Он имеет два самых больших применения, одно из них заключается в том, что переменные внутри функции могут быть прочитаны, как упомянуто выше, а другой заключается в том, что значения этих переменных всегда хранятся в памяти.
Как понять это предложение? Пожалуйста, смотрите код ниже.
Функция f () {var n =; // nAdd - глобальная переменная, которая не объявляется с использованием var. Эта переменная теперь указывает на анонимную функцию, объявленную внутри функции f nadd = function () {n+=} function f () {alert (n); } return f; } var result = f (); // Результат - это f result (); // Первый вызов к функции результата nadd (); // nadd представляет анонимную функцию, объявленную внутри функции f, nadd () является результатом анонимной функции (); // второй вызов к функции результата 1000Результаты работы:
В этом коде результат фактически является функцией закрытия F2. Всего он работает дважды, первое значение составляет 999, а второе значение составляет 1000. Это доказывает, что локальная переменная n в функции F1 сохранилась в памяти и не полностью очищена после вызова F1.
Почему это происходит? Причина в том, что F1 является родительской функцией F2, а F2 назначается глобальной переменной, которая заставляет F2 всегда в памяти, а существование F2 зависит от F1. Следовательно, F1 всегда находится в памяти и не будет переработана механизмом сбора мусора после завершения вызова.
Другая примечательная точка в этом коде заключается в том, что строка «nadd = function () {n+= 1}» сначала используется перед NADD, поэтому NADD является глобальной переменной, а не локальной переменной. Во -вторых, значение NADD является анонимной функцией, и сама эта анонимная функция также является закрытием, поэтому NADD эквивалентен сеттеру, который может работать на локальных переменных внутри функции вне функции.
5. Примечания об использовании закрытия
1) Поскольку закрытие приведет к тому, что все переменные в функции хранятся в памяти, а потребление памяти очень большое, закрытие нельзя злоупотреблять, в противном случае это вызовет проблемы с производительностью веб -страницы и может привести к утечке памяти в IE. Решение состоит в том, чтобы удалить все локальные переменные, которые не используются перед выходом на функцию.
2) Закрытие изменит значение переменной внутри родительской функции вне родительской функции. Следовательно, если вы используете родительскую функцию в качестве объекта, используйте закрытие в качестве общедоступного метода и используйте внутреннюю переменную в качестве ее личного свойства, будьте осторожны, чтобы не изменить значение внутренней переменной родительской функции по желанию.
6. Мыслительные вопросы
Если вы можете понять выполненные результаты следующих двух фрагментов кода, вас следует считать пониманием механизма выполнения закрытия.
Код фрагмент 1:
var name = "окно"; var object = {name: "my object", getNamefunc: function () {return function () {return this.name; }; }}; alert (object.getNamefunc () () ());Результаты работы:
Код фрагмент два:
var name = "окно"; var object = {name: "my object", getNamefunc: function () {var that = this; return function () {return that.name; }; }}; alert (object.getNamefunc () ());Результаты работы:
Следующие комментарии добавляются в код для анализа выполненных результатов двух вышеуказанных фрагментов кода:
Код фрагмент 1:
Анализ заключается в следующем:
/*В JavaScript, глобальные объекты JavaScript, глобальные функции и глобальные переменные, которые мы объявляем, автоматически станут членами объекта Window. Глобальные переменные являются свойствами окна объектов. Глобальные функции - это методы оконных объектов. */var name = "the Window"; // Объявит глобальное имя переменной переменной, и в настоящее время имя глобального переменной переменной автоматически станет атрибутом Owne Object // Proof: alert ("window.name:"+window.name); // Вы можете получить доступ к имени в форме window.name (имя объекта. Время. Объект объекта глобальной переменной автоматически станет атрибутом объекта окна var object = {name: «my object», // Имя атрибута объекта getNamefunc: function () {// getNamefunc функция объекта // возвращаемое значение getNamefunc метода объекта - это анонимная функция (), какой объект, который объект, объект, который объект является объектом, который объект, который объект, объект, может быть, объект, который объект, объект, объект. к какому объекту. // Докажите, что это в анонимной функции представляет собой окно -объект вместо objectAlert («Результат объекта этого ==:«+(это == объект)); Alert («Результат окна This ==:»+(окно this ==)); вернуть this.name; // Поскольку это представляет собой окно -объект, тогда это. }}; // Доказательство: Объект Global объект является атрибутом Attribute of Abode Object ("window.object:"+window.object); alert ("window.object.name:"+window.object.name);/*После вызова метода getNamefunc, анонимный метод возвращается. В настоящее время RETFN представляет анонимный метод. Теперь это эквивалентно предоставлению анонимному методу имени retfn. В настоящее время функция retfn автоматически становится функцией объекта окна*/var retfn = object.getNamefunc (); alert (retfn ()); // Вызов возвращаемого анонимного метода, так кто вызывает этот анонимный метод? Это окно -объект // доказательство: функция RETFN является функцией Alert Ondate Object ("window.retfn ():"+window.retfn ()); // Вы можете вызвать метод retfn в форме window.retfn () (имя объекта. Имя метода), тогда она доказывает, что функция retfn является функцией окна объекта окна.Код фрагмент два:
Анализ заключается в следующем:
var name = "the Window"; // Global Variable name // Global ObjectVar object = {name: "my Object", getNamefunc: function () {/*Какой объект это представляет в это время? Это представляет объект объекта. Какой объект вызывает функцию, где она находится? Это относится к тому, какой объект был выполнен, что = это, и это также представляет объект объекта*/var, что = this; // это локальная переменная, объявленная в функции getNamefunc // доказывает, что это в функции getNamefunc представляет объект объекта вместо windowalert («Это результат объекта == объект:» (this == объект)); Alert («Результат окна This ==:«+(окно this == Window)); // докажите, что представляет Aboy Object Alert («that == Результат объекта:»+(that == Object)); return function () {/*, которая является локальной переменной, объявленной в функции getNamefunc. При нормальных обстоятельствах после завершения вызова функции getNameFunc локальная переменная, которая будет переработана GC JavaScript, освобождая пространство памяти, занятую локальной переменной, но теперь это может использоваться нормально и не переработано. Причина в том, что GetNamefunc является родительской функцией анонимной функции. После того, как функция getNamefunc вызвана, анонимная функция будет возвращена и назначена глобальной переменной retfn, что приводит к тому, что анонимная функция всегда находится в памяти, а существование анонимной функции зависит от функции getNamefunc. Следовательно, функция GetNameFunc всегда находится в памяти и не будет переработана механизмом сбора мусора после завершения вызова. Поскольку функция getNamefunc всегда находится в памяти, локальная переменная, объявленная внутри функции getNameFunc, всегда будет существовать в памяти. Поскольку он существует, конечно, это может продолжать использоваться. */вернуть это. }}; var retfn = object.getNamefunc (); // После вызова метода getNamefunc возвращается анонимный метод. В настоящее время RETFN представляет анонимный метод, который в настоящее время эквивалентен предоставлению анонимному методу, имя является retfn Alert (retfn ());Наконец, я также приложил пример, который я написал, когда изучал закрытие JavaScript раньше:
<script type = "text/javascript"> function a () {var i =; // Объявит локальную переменную I внутри функции A/Объявит подфункцию bfunction b () {alert ("i ="+(++ i)); // Доступ к локальной переменной I объявил внутри функции a in function a} reture b; // return arder function b}/**После areable var var var at var var var at (). функция б. беременный Переменная, которую я использует. После выполнения c () будет появляться окно, чтобы отобразить значение I (в первый раз), и этот код фактически создает закрытие, потому что переменная C вне функции A относится к функции B внутри функции a. То есть: когда внутренняя функция B функции A ссылается переменная внешняя функция A, создается так называемое закрытие «закрытия». После того, как A была выполнена и возвращена, закрытие делает механизм сбора мусора JavaScript GC не перерабатывает ресурсы, занятые A, потому что выполнение внутренней функции B необходимо полагаться на переменную в */A (); // Там определенно будет место в памяти. После того, как a () выполняется, GC переработает пространство памяти, выделяемое для i var c = a (); // Это использование, GC не будет рассматривать I как мусор и c (); // эквивалентное вызову b (), результат: i = c (); // Результат: i = c (); // Результат: i = c ();Результаты работы:
Приведенный выше контент представляет собой подробное объяснение кода закрытия JavaScript (закрытие) знаний JavaScript, обобщенные (16), представленные редактором. Я надеюсь, что это будет полезно для всех!