Замыкания в Javascript
Вложений: 1
Очень много инфо о замыканих, но немного размыта информация самого смысла его использования.
Главный смысл замыканий сохранить локальную переменную после завершения функции и использовать при запуске 2-ого, 3-его, n-ого раза запуском главной функции в котором встроена внутренняя? <!DOCTYPE html> <html> <head> <meta charset="utf-8"> </head> <body> <script> var fn = (function() { var numberOfCalls = 0; return function() { return ++ numberOfCalls; } })(); </script> </body> </html> Интересует, обычно функцию объявляют вначале круглые скобки, а затем фигурные и там список команд в фигурных, а здесь получается круглые и снова круглые? Разве так еще можно объявлять функцию? Речь про концовку Цитата:
Вот показал на скрине, функцию объявляют сразу с двумя подряд круглыми скобками что ли или это одновременно и объявление и вызов этой же функции? Разве так можно? |
Цитата:
|
Цитата:
Цитата:
|
Цитата:
Когда я присваиваю переменной fn функцию, а в ней еще внутренняя анонимная функция, переменная fn содержит ссылку на функцию в функции, то есть 2 функции или ссылку только на анонимную внутреннюю одну? |
Цитата:
|
Это все потому что стоит return function(),
А если бы return не стоял для вызова анонимной функции тогда все равно fn содержал бы ссылку на анонимную функцию или он содержит ссылку только на то что возвращает return главной функции fn? |
denis_alekss,
console.log(fn) |
denis_alekss,
если интересно уберите строку var numberOfCalls = 0; но сохраните прежний функционал и даже сделайте его более универсальным. <!DOCTYPE html> <html> <head> <meta charset="utf-8"> </head> <body> <script> var fn = (function() { var numberOfCalls = 0; return function() { return ++ numberOfCalls; } })(); console.log(fn());//1 console.log(fn());//2 console.log(fn());//3 var foo = (function() { /*var numberOfCalls = 0;*/ return function() { return ++ numberOfCalls; } })(); console.log(foo());//1 console.log(foo());//2 console.log(foo());//3 </script> </body> </html> |
Если запустить ваш вариант, вначале выдаст
1 2 3 А затем ошибку: Цитата:
Если так: var foo = (function() { /*var numberOfCalls = 0;*/ return function() { numberOfCalls = 0; return ++ numberOfCalls; } })(); Выведет 3 раза подряд цифру 1 вместо 1 2 3 |
denis_alekss,
обе функции должны выдавать одно и тоже, плюс foo будет более универсальной. это не меняйте return function() { return ++ numberOfCalls; } с остальным делайте, что хотите , var numberOfCalls = 0; не использовать |
Вложений: 1
Ничего не менял, запустил ваш код, функция foo не определена выдает, вот фото ниже, сделал скриншот
|
Цитата:
|
Если для теста написать даже вот так:
var foo = (function() { /*var numberOfCalls = 0;*/ alert('Привет'); return function () { return alert('Пока'); } })(); Вначале простреляет 1 Привет, а затем 3 пока, и каждый раз когда будет выводится слово Пока, будет выводится в консоль undefined, значит переменная foo ссылается только на внутренню анонимную функцию ? НА эту если возвратимся к коду в 1-ом посте: return function() { return ++ numberOfCalls; } |
denis_alekss,
надо дописать в пару мест недостающее, что-бы код стал рабочим. var foo = (function() { return function() { return ++ numberOfCalls; } })(); |
denis_alekss,
ок ... что-то пошло не так, наверно я плохо сформулировал задачу... var foo = (function(numberOfCalls) { return function() { return ++numberOfCalls; } })(0); console.log(foo());//1 console.log(foo());//2 console.log(foo());//3 |
Этим кодом вы показываете что ссылка все-таки идет на внутреннюю функцию, вы просто передаете аргумент 0 функции fn, а им пользуется внутренняя анонимная функция. Если передать вместо 0 передать к примеру 8, счетчик пойдет с 9 из-за инкремента и вся работа пойдет во внутренней а не со внешней функции
|
denis_alekss,
:yes: |
Немного другая версия этого же случая:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> </head> <body> <script> Function.prototype.bind = function(context) { var fn = this; return function() { return fn.apply(context, arguments); }; } var HelloPage = { name: 'Вася!!!', init: function() { alert('Hello, ' + this.name); } } window.onload = HelloPage.init.bind(HelloPage); </body> </html> Если поменять эту строку: Function.prototype.bind на Function.prototype.call разницы при выводе не происходит. Если поменять эту строку: window.onload = HelloPage.init.bind(HelloPage); на window.onload = HelloPage.init.apply(HelloPage); Также вывод одинаковый. В этом месте также используется замыкание Function.prototype.call = function(context) { return function() { return this.apply(context, arguments); }; } Здесь this ссылается на объект HelloPage благодаря функции call или bind если указать в строке Function.prototype.bind? Можно ли обойтись в этом коде для получения идентичного результата без замыканий если я хочу вызвать метод объекта передав свойство Петя с этого же объекта в метод? |
Цитата:
Можно определить замыкание и без IIFE, просто внешнюю функцию надо будет вызвать явно: <body> <script> function getMyClosure(){ var count = 0; var closure = function(){ return count++; } return closure; } var counter = getMyClosure(); //вызываем явно и сохраняем ссылку на внутреннюю функцию в нашей переменной </script> <button onclick="alert(counter())">Press Me</button> </body> |
Цитата:
Почему нельзя просто вызвать getMyClosure() и передать в Onclick? |
Цитата:
Цитата:
<body> <script> function getMyClosure(){ var count = 0; var closure = function(){ return count++; } return closure; } var counter1 = getMyClosure(); //первое замыкание var counter2 = getMyClosure(); //второе var counter3 = getMyClosure(); //третье </script> <button onclick="document.getElementById('btn1').innerText=counter1()">Button1 (<span id="btn1">-</span>)</button> <button onclick="document.getElementById('btn2').innerText=counter2()">Button2 (<span id="btn2">-</span>)</button> <button onclick="document.getElementById('btn3').innerText=counter3()">Button3 (<span id="btn3">-</span>)</button> </body> P.S.: Если ещё не читали: https://learn.javascript.ru/closure |
Часовой пояс GMT +3, время: 06:57. |