Каково точное использование закрытия? - PullRequest
0 голосов
/ 30 января 2019

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

Закрытие:

function add(x) {
    return function(y) {
    return function(z) {
    return x + y + z;
    } 
    };
}

console.log(add(1)(2)(3))

Вместо замыкания Просто мы можем передать три параметра в один метод.

function add(x,y,z) {
   
    return x + y + z;
}

console.log(add(1,2,3))

Так почему мне нужно использовать замыкание?

Ответы [ 4 ]

0 голосов
/ 30 января 2019

В этом примере нет реальной разницы в выводе.Однако давайте сделаем это еще проще:

function add(a) {
  return function(b) {
    return a+b;
  }
}


console.log(add(1)(2));
function add(a, b) {
  return a+b;
}

console.log(add(1, 2));

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

function add(a) {
  return function(b) {
    return a+b;
  }
}

let numbers = [1, 2, 3, 4, 5, 6];

//lets add the same number to all members of the array:
const numberToAdd = 5;

//traditionally
const newArray = []; //make a new array

for (let num of numbers) { //define a loop
  newArray.push(num + numberToAdd); //populate the array
}

console.log(newArray);

//functional
const mappedArray = numbers.map(num => num + numberToAdd); //using .map to handle everything
console.log(mappedArray);

//using the function we have
const betterMappedArray = numbers.map(add(numberToAdd));
console.log(betterMappedArray);

Таким образом, функциональный подход с помощью .map короче и проще, но может быть еще более улучшен путем передачи функции.Без функции add вы по-прежнему передаете функцию, вы определяете новую функцию сложения каждый раз, когда вы хотите просто добавить что-либо в массив.Если вы хотите добавить переменные суммы, то без add вам нужно создать две новые функции, которые в основном все делают одно и то же

function add(a) {
  return function(b) {
    return a+b;
  }
}

let numbers = [1, 2, 3, 4, 5, 6];


console.log("using .map() with new functions");
console.log(
  numbers
    .map(num => num + 5)
    .map(num => num + 10)
);

console.log("using .map() with add()");
  
console.log(
  numbers
    .map(add(5))
    .map(add(10))
);

Как видите, поставить бок о бок кажется довольно расточительным, чтобы каждый раз создавать новые функции.Даже при наличии подписи add(a, b), то есть двух аргументов, вам придется вызывать numbers.map(num => add(num, 5)), что ничего не улучшит.

Имейте в виду, что add действительно просто - у вас может быть функцияэто сложнее.Тем не менее, перейдя к простому примеру, давайте перепишем пример, чтобы показать, как он может быть полезен:

function add(a) {
  return function(b) {
    return a+b;
  }
}

const shoppingCart = [
  {name: "item1", price: 1},
  {name: "item2", price: 2},
  {name: "item3", price: 3},
  {name: "item4", price: 4},
  {name: "item5", price: 5},
  {name: "item6", price: 6},
];

const applyHandlingTax = add(5);
const applyShippingTax = add(10);

const numbers = shoppingCart.map(item => item.price); //extract prices from the shopping cart

const finalPrices = numbers
  .map(applyHandlingTax)
  .map(applyShippingTax);

console.log(finalPrices);

Это наивный пример с преувеличенными числами, но он просто показывает, что мы можем сделать здесь.Функционально он такой же, как и в предыдущем фрагменте, но, как вы можете видеть, теперь у нас есть бизнес-логика практически без изменений.

  • Мы определили applyHandlingTax как добавление 5.Мы также определили applyShippingTax для добавления 10.
  • Обе эти функции являются функциями, поэтому мы можем применить их через .map непосредственно к набору результатов, который у нас есть, уменьшая объем кода, который мыдолжен написать.
  • Бизнес-правило легко понять, поскольку вы пишете довольно читабельный для человека код - вам нужно совсем немного знаний о программировании, чтобы понять, numbers.map(applyHandlingTax).map(applyShippingTax) применяет налог на доставку и обработку к каждому из чисел.И как разработчик ясно, что вы добавляете налог на доставку и обработку.
  • Если мы уверены, что add работает правильно, то по определению все, что происходит из этого, также будет работать - нет необходимости проверять applyShippingTax.Фактически, нечего проверять - нет тела функции, мы не написали для него никакой логики, мы используем только результат функции для него.
  • единственный значимый код, который мы написали, предназначен для определения add и извлечения цен из предметов.Даже в этом случае последний может быть легко абстрагирован так же, как мы сделали с add, поэтому мы можем применить его к любому какому-либо набору результатов

function extract(name) {
  return function(item) {
    return item[name];
  }
}

const shoppingCart = [
  {name: "item1", price: 1},
  {name: "item2", price: 2},
  {name: "item3", price: 3},
  {name: "item4", price: 4},
  {name: "item5", price: 5},
  {name: "item6", price: 6},
];

const people = [
  {name: "Alice",  drives: "Audi"},
  {name: "Bob",    drives: "BMW"},
  {name: "Carol",  drives: "Citroen"},
  {name: "David",  drives: "Dodge"},
  {name: "Esther", drives: "EDAG"},
  {name: "Fred",   drives: "Ford"},
];

const prices = shoppingCart.map(extract('price'));
console.log(prices);

const names = people.map(extract('name'));
const cars = people.map(extract('drives'));
console.log(names);
console.log(cars);

Даже с довольно тривиальным примером add мы можем продвинуться довольно далеко.Особый стиль написания add известен как curry - вместо одновременного принятия X количества параметров, функция возвращает другую функцию, которая принимает X - 1 , пока не будет удовлетворено.

Функции, которые работают с другими функциями - либо производящие их (как add делает), потребляющие их, либо обе они называются функциями высшего порядка .Если мы будем использовать их и последовательно каррировать, мы попадем на территорию функционального программирования .Написание полностью функционального стиля не является обязательным условием, чтобы извлечь из этого пользу - как мы видели в add, вы можете написать простое приложение, не используя много кода, даже если мы применяем бизнес-правила.

0 голосов
/ 30 января 2019

Это довольно синтетический и в основном бесполезный пример.Короче говоря, вам нужны замыкания, потому что Javascript использует много кода, основанного на обратном вызове, и вы хотите сохранить доступ к предыдущей области в следующих обратных вызовах:

function foo(bar) {
    setTimeout(function () {
        alert(bar);
    });
}

Механизм закрытия здесь позволяет alert(bar) сохранятьиметь доступ к bar, даже если foo уже завершил выполнение и все его переменные должны были выйти из области видимости.Вот что такое закрытие , оно закрывает область и сохраняет ее доступной.

0 голосов
/ 30 января 2019

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

function add(x) { return function(y) { return x + y; }; }

const add2 = add(2);
console.log(add2(1)); // 3
console.log(add2(40)); // 42

Конечно, если бы функция add не была карри, вы могли бы использовать

function add2(y) {
  return add(2, y);
}

, но это излишне многословно.


Конечно, это подчеркивает только один случай использования замыканий, есть и многие другие .

0 голосов
/ 30 января 2019

'add (1) (2) (3)' и 'add (1,2,3)' имеют одинаковый результат.но я могу многое сделать с первым.Позвольте привести пример.

function add(x) {
    return function(y) {
    return function(z) {
    return x + y + z;
    } 
    };
}

const WELCOME_POINT = 10;
const VIP_POINT = 20;
function myPointCaculator(currentPoint, predicate) {
  if(typeof predicate === 'number')
    return currentPoint + predicate;
  else if(typeof predicate === 'function') {
    return currentPoint + predicate(WELCOME_POINT);
  } else {
    return currentPoint;
  }
}
  
const eventPoint = add(WELCOME_POINT)(VIP_POINT);
myPointCaculator(WELCOME_POINT, eventPoint);
'add (1,2,3)' будет выполняться напрямую, но 'add (1) (?) (?)' Может быть передано в функцию в качестве параметра.Это другое.Речь идет о «curry» и «функции первого порядка». Функция первого порядка в javascript может сделать вас кодом с функциональным программированием.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...