var makeCounter = function() {
var privateCounter = 0;
function changeBy(val) {
privateCounter += val;
}
return {
increment: function() {
changeBy(1);
},
decrement: function() {
changeBy(-1);
},
value: function() {
return privateCounter;
}
}
};
var Counter1 = makeCounter();
var Counter2 = makeCounter();
console.log(Counter1.value()); /* logs 0 */
Counter1.increment();
Counter1.increment();
console.log(Counter1.value()); /* logs 2 */
console.log(Counter2.value()); /* logs 0 */
问题的背景:我是初学小白,接触了作用域,作用域链,原型,继承,还有一点点闭包的知识。这段计时器代码是我在看这个链接中 https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Closures 学习闭包知识遇见的。我觉得上面的代码类似于《JS高阶程序设计》中用工厂模式创建对象的方法。不知道这么理解对不对。
最重要的疑惑就是,var Counter1 = makeCounter(); 在执行以后,makeCounter() 是一个函数,执行完以后会返回函数,那么 Counter1 里面存储的是指向返回这个函数的指针。同理,Counter2 里面也是返回的这个函数的指针。也就是,Counter1 和 Counter2 保存的是同一个函数的指针。那么,为什么通过 Counter1 改变了这个函数的 value 值,Counter2 的 value 值不会受到影响呢?
谢谢各位前辈解答~
前端的不怎么会,但这个不是工厂模式,这只是在一个方法内调用方法进行算术运算然然后返回一个基本类型的值。
工厂模式是专门生产某一对象的,比如使用框架中不可缺少的session对象 就是由SqlSessionFactory生产出来的。而非简单的返回一个基本数据类型的值。
1.不是工厂模式,工厂模式是生产有共性但类型不同的对象,makeCounter()
返回的是同一个类型的对象。
2.Counter1
里的privateCounter
和和Counter2
的privateCounter
只是名字相同,但地址是不同的,自然不会相互影响。通常一个变量的生命期受限于作用域,而闭包实际是延长了其生命期,而延长生命期的方法就只有为变量动态分配空间为不是使用原始的栈空间。
PS:我没接触过JS,不过不同语言的原理都是相通的。
本质上value函数控制的privateCounter并不是一个引用类型值,Counter1 和Counter2的privateCounter实际上是var了一个局部变量
count1 count2是两个不同的闭包 虽然函数指针一样 但是操作的值有两个副本 各自操作的值不一样
makeCounter 函数是工厂函数,因为它返回一个对象。这种形式好像形成了闭包,Counter1 和 Counter2 是分别实例化的,所以 privateCounter 的值是不相干的。