Мой пример закрытия не работает, как я учил - PullRequest
0 голосов
/ 09 мая 2018

Я пытаюсь выяснить замыкания и создал этот простой пример, в котором вы вызываете функцию greet с именем, а после первого вызова приветствие должно содержать предыдущие заданные имена.

Так что, если вы позвоните greet ('Andrew') и greet ('Joseph'), я ожидаю увидеть на консоли:

Hello Andrew
Hello Andrew, Joseph 

Вот мой код: https://codepen.io/anon/pen/pVpBdy

let greet = function(name) {
    let greeting = 'Hello ';

    let updateGreet = function() {
      greeting = greeting + ', ' + name; 
    }

    let printGreet = function() {
      console.log(greeting + name);
      updateGreet();
    }

    return printGreet();
} 

greet('Andrew');
greet('Joseph');

Результат, который я вижу:

Hello Andrew
Hello Joseph 

Кажется, приветствие переинициализируется каждый раз, когда я вызываю greet (), и я понятия не имею, почему.

Пожалуйста, помогите мне понять это.

Ответы [ 4 ]

0 голосов
/ 09 мая 2018

Закрытие не наблюдается, потому что функция greet не возвращает функцию, а скорее вызывает функцию, что приводит к значению undefined. Чтобы наблюдать замыкание, внешняя функция может быть вызвана как IIFE и должна возвращать функцию printGreet, которая сохраняется в переменной greet. Теперь greet имеет ссылку на функцию printGreet, которая все еще поддерживает связь с лексической средой.

let greet = (function() {
  let greeting = 'Hello ';

  let updateGreet = function(name) {
    greeting = greeting + ', ' + name; 
  }

  let printGreet = function(name) {
    console.log(greeting + ', '+ name);
    updateGreet(name);
  }

  return printGreet;
}());

greet('Andrew');
greet('Joseph');
0 голосов
/ 09 мая 2018

Ваш текущий greet можно вызвать создать автономный объект - объект затем сохранит имена. Каждый раз, когда вы вызываете greet, вы создаете отдельную переменную greeting, инкапсулированную в другом объекте.

Самый простой метод - это немедленное выполнение функции, чтобы все вызовы greet ссылались на один и тот же объект.

Вы должны также передать переменную name в updateGreet:

const greet = (() => {
  let greeting = 'Hello';
  const updateGreet = function(name) {
    greeting = greeting + ', ' + name;
  }
  const printGreet = function(name) {
    console.log(greeting + ', ' + name);
    updateGreet(name);
  }
  return printGreet;
})();

greet('Andrew');
greet('Joseph');
greet('Bob');

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

0 голосов
/ 09 мая 2018

Я собираюсь предположить, что вы не слишком заботитесь о получении этого конкретного результата, но вы заботитесь о понимании концепции.Поэтому я упростил ваш пример до этого:

function greet (greeting) {

    return function person (name) {
        console.log(greeting + ',' + name)
    }

}

helloGreeting = greet('hello')

helloGreeting('andrew') // 'hello, andrew'
helloGreeting('joseph') // 'hello, joseph'

Здесь происходит то, что при первом вызове greet функция возвращает закрытие - person.Закрытие - это функция, объявленная внутри другой функции, и благодаря тому, что она объявлена ​​внутри этой функции, она имеет доступ ко всему, что определено во внешней функции.

Поэтому после вызова greet('hello') js возвращает personфункция, и эта функция имеет доступ к переменной greeting, определенной ранее.

В частности, контекст выполнения функции person содержит переменную приветствия.Вы можете думать о контексте выполнения как о блоке, и каждый раз, когда вы запускаете person, вызывая helloGreeting, этот блок также содержит переменную greeting, определенную как hello.

прелесть этого в том, что теперьВы также можете определить другие приветствия.

niceToMeetYouGreeting = greet('niceToMeetYou')
yoGreeting = greet('Yo')

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

0 голосов
/ 09 мая 2018

Переменная greeting связана с областью действия функции greet. Таким образом, каждый раз, когда вы вызываете greet(), переменная приветствия переинициализируется с помощью let greeting = 'Hello ';

Для достижения желаемого результата вы можете переместить let greeting = 'Hello ' за пределы greet, чтобы он остался.

let greeting = 'Hello ';
let greet = function(name) {
    let updateGreet = function() {
      greeting = greeting + ', ' + name; 
    }

    let printGreet = function() {
      console.log(greeting + name);
      updateGreet();
    }

    return printGreet();
} 

greet('Andrew');
greet('Joseph');
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...