您可以重置一个变量来存储调用包含闭包的函数的结果吗?

时间:2018-06-22 20:41:00

标签: javascript

是否可以重置调用包含闭包的函数的变量?在下面的示例中,该名称为counter。 (请注意,我不熟悉闭包,因此某些注释可能是错误的。)

function makeCounter() {
 let count = 0;
 return function() {
   ++count;
   return `count equals ${count}`; 
 };
};

// If you just call it two times without storing the result in a variable, count is reset to zero each time
console.log(makeCounter()()); // count equals 1
console.log(makeCounter()()); // count equals 1

// Since the counter variable holds a reference to the result of the outer function's call (which is the inner returned function, which "closes over" count), the JavaScript engine won't wipe it from memory.
let counter = makeCounter();

// As expected, calling counter again updates it (storing the updated count value)
console.log(counter()); // count equals 1
console.log(counter()); // count equals 2 <-- Can you reset count as stored in counter?

4 个答案:

答案 0 :(得分:2)

使用该代码,无法以任何方式重置count变量,这就是闭包的力量。

您可以做的是修改计数器,并实现方法reset

function makeCounter() {
 let count = 0;
 
 const counter = function() {
   ++count;
   return `count equals ${count}`; 
 }
 
 counter.reset = () => count = 0;
 
 return counter;
};

const counter = makeCounter();
console.log(counter());
console.log(counter());
counter.reset();
console.log(counter());

您还可以在函数中添加一个reset参数。

function makeCounter() {
    let count = 0;
    return function(reset) {
        if (reset)
            count = 0;
        ++count;
        return `count equals ${count}`;
    };
}

答案 1 :(得分:1)

考虑将参数传递给计数器函数以将其重置为0:

function makeCounter() {
  let count = 0;
  return function(reset) {
    if (reset === true) {
      count = 0;
    }
    ++count;
    return `count equals ${count}`; 
  };
};

console.log(counter()); // count equals 1
console.log(counter()); // count equals 2
console.log(counter(true)); // count equals 1

答案 2 :(得分:1)

目前,counter仅能接受一条(未命名)消息,其副作用是增加内部状态count。为了添加重置功能,您应该增加counter以便接受更多消息。

在这方面,一种可行的方法是通过字符串参数引入显式消息传递(另请参见SICP,Chapter 3中的练习3.11):

 function makeCounter() {
     let count = 0;
     return function (msg) {
         switch (msg) {
             case 'increment': count++; return count;
             case 'reset': count = 0; break;
             default: throw new Error('unknown message');
         };
     };
 }

 let counter = makeCounter();
    
 console.log(counter('increment')); // output: 1
 console.log(counter('increment')); // output: 2
    
 counter('reset');
 console.log(counter('increment')); // output: 1

但是,在这一点上,我们可以利用JavaScript msg类型来机械地替换object上的显式调度,如:

function makeCounter() {
    let count = 0;
    return {
        increment: function() { count++; return count; },
        reset: function() { count = 0; }
    };
}

let counter = makeCounter();

console.log(counter.increment());  // output: 1
console.log(counter.increment());  // output: 2
    
counter.reset();
console.log(counter.increment());  // output: 1

因此,按照 closures are a poor man's object makeCounter使得每种消息类型都与相应的闭包相关联,可以实现一种方便的解决方案。 em>参数。

答案 3 :(得分:0)

您可以将重置计数传递给以下功能

function makeCounter() {
 let count = 0;
 return function(startCount) {
   count = startCount ? startCount : ++count;
   return `count equals ${count}`; 
 };
};

let counter = makeCounter();

// As expected, calling counter again updates it (storing the updated count value)
console.log(counter()); // count equals 1
console.log(counter()); // count equals 2

// now counter will reset to value passed
console.log(counter(1));