关于javascript封闭的w3schools例子几乎没用吗? [关闭]

问题描述 投票:1回答:4

我在w3schools上阅读这个关于应用于“反困境”的Javascript闭包的例子:

https://www.w3schools.com/js/js_function_closures.asp

在实际使用中,这个例子似乎几乎是无稽之谈。当我无法保护包含函数本身的变量“add”时,为什么要将变量“counter”包装到闭包中,以防止意外修改全局范围?

更具体一点......我有这个代码:

var add = (function () {
    var counter = 0;
    return function () {return counter += 1;}
})();

add();
add();
add();

// the counter is now 3

W3schools在开始时说:“问题是,页面上的任何脚本[在全局范围内]都可以更改计数器,而无需调用add()。”......上面提到的闭包是一个解决方案。好。但是如何保护“添加”免于订阅?似乎这个解决方案只能解决问题,使这个例子实际上毫无用处。你能告诉我为什么这种副作用不成问题吗?

javascript closures counter
4个回答
4
投票

在w3schools给出的例子中,他们用上述闭包解决的问题是保护变量counter不被直接修改。如果counter在全局范围内,然后你定义了一个函数,比如add来将计数器递增一些值,那么你所做的就是为代码的其他部分定义一个与counter变量交互的接口。

当您在某些数据和代码库的其他部分之间定义接口时,您可能希望强制执行该接口。换句话说,如果你将counter放在全局范围内,那么就没有办法强制使用你的add函数,因为我可以这样做:counter += 7就在全局范围内。

counter变量包装在闭包中允许您从全局范围隐藏counter变量,这意味着修改计数器的唯一方法是通过add函数。这通过防止直接修改add变量的值来强制使用counter

所以这是一个简单但很好的例子,说明了如何使用闭包来创建私有变量。


1
投票

它并没有用,因为它将counter作为add的财产。如果你需要保护add,你可以将它包装在另一个封闭中。

var add = "something";
(()=>{
    var add = (function () {
        var counter = 0;
        return function () {return counter += 1;}
    })();
    console.log(add());
    console.log(add());
})();
console.log(add);

当然,在现实生活中,你应该首先避免使用像add这样的超级通用名称,而在现实生活中,如果你需要你的方法来获得属性,你可能会使用OOP代替......

class counter{
    constructor(){
        this.counter = 0;
    }
    add(){
        this.counter++;
    }
}

var c = new counter();
c.add();
c.add();
console.log(c.counter);

如果您只是想确保永远不会重新分配变量名,您可以使用const(JS“常量”)代替。

const add = (function(){
    var add = 0;
    return function(){ return ++add };
})();

try{
    // this won't work
    add = "something";
}catch(e){
    console.log(e.message);
}

// Add is still a function here
console.log(add());
console.log(add());
console.log(add());

0
投票

出于教育目的,通常将示例简单化。让他们减少分心。

该示例试图显示的是,您只能使用此闭包增加计数器。你不能减少,你不能到达计数器变量做任何其他事情。你当然可以抛弃整个功能,但这不是你偶然会做的事情。

意外地改变不在闭包中的变量的值很容易。


-1
投票

这是一个“问题较少”和“更有用”的例子。

记忆化

var fibonacci = (function() {
  var memo = {};

  return function f(n) {
    if (!(n in memo)) {
      memo[n] = n === 0 || n === 1 ? n : f(n - 1) + f(n - 2);
    }

    return memo[n];
  }
})();

Closure允许访问“memo”对象,该对象存储其以前的所有结果。

© www.soinside.com 2019 - 2024. All rights reserved.