我正在尽最大努力理解JavaScript闭包。

通过返回一个内部函数,它可以访问直接父函数中定义的任何变量。

这对我有什么用?也许我还没完全搞清楚。我在网上看到的大多数示例都没有提供任何真实的代码,只是一些模糊的示例。

有人能告诉我一个闭包的真实用法吗?

比如这个吗?

var warnUser = function (msg) {
    var calledCount = 0;
    return function() {
       calledCount++;
       alert(msg + '\nYou have been warned ' + calledCount + ' times.');
    };
};

var warnForTamper = warnUser('You can not tamper with our HTML.');
warnForTamper();
warnForTamper();

当前回答

闭包的另一个常见用途是将方法中的this绑定到特定对象,允许在其他地方调用它(例如作为事件处理程序)。

function bind(obj, method) {
    if (typeof method == 'string') {
        method = obj[method];
    }
    return function () {
        method.apply(obj, arguments);
    }
}
...
document.body.addEventListener('mousemove', bind(watcher, 'follow'), true);

每当鼠标移动事件触发时,都会调用watch .follow(evt)。

闭包也是高阶函数的重要组成部分,通过参数化不同部分,可以将多个相似函数重写为一个高阶函数,这是非常常见的模式。举个抽象的例子,

foo_a = function (...) {A a B}
foo_b = function (...) {A b B}
foo_c = function (...) {A c B}

就变成了

fooer = function (x) {
    return function (...) {A x B}
}

其中A和B不是语法单位,而是源代码字符串(不是字符串字面量)。

具体示例请参见“用函数简化我的javascript”。

其他回答

闭包的使用:

闭包是JavaScript最强大的特性之一。JavaScript允许函数嵌套,并授予内部函数对外部函数中定义的所有变量和函数的完全访问权(以及外部函数可以访问的所有其他变量和函数)。但是,外部函数不能访问内部函数内部定义的变量和函数。

这为内部函数的变量提供了一种安全性。此外,由于内部函数可以访问外部函数的作用域,如果内部函数能够在外部函数的生命周期之后继续存在,那么外部函数中定义的变量和函数将比外部函数本身的生命周期更长。当内部函数以某种方式对外部函数之外的任何作用域可用时,就会创建闭包。

例子:

<script>
var createPet = function(name) {
  var sex;
  
  return {
    setName: function(newName) {
      name = newName;
    },
    
    getName: function() {
      return name;
    },
    
    getSex: function() {
      return sex;
    },
    
    setSex: function(newSex) {
      if(typeof newSex == "string" && (newSex.toLowerCase() == "male" || newSex.toLowerCase() == "female")) {
        sex = newSex;
      }
    }
  }
}

var pet = createPet("Vivie");
console.log(pet.getName());                  // Vivie

console.log(pet.setName("Oliver"));   
console.log(pet.setSex("male"));
console.log(pet.getSex());                   // male
console.log(pet.getName());                  // Oliver
</script>

在上面的代码中,外部函数的name变量可以被内部函数访问,除了通过内部函数,没有其他方法访问内部变量。内部函数的内部变量充当内部函数的安全存储。它们保存“持久的”但安全的数据,供内部函数使用。这些函数甚至不需要赋值给变量,也不需要有名称。 详情请阅读此处。

闭包是一种创建生成器的有用方法,它是一个按需递增的序列:

var foobar = function(i){var count = count || i; return function(){return ++count;}} 巴兹 = 福巴(1); console.log(“First Call: ” + baz());2 console.log(“第二次调用: ” + baz());3

区别总结如下:

Anonymous functions                                    Defined functions

Cannot be used as a method                             Can be used as a method of an object

Exists only in the scope in which it is defined        Exists within the object it is defined in

Can only be called in the scope in which it is defined Can be called at any point in the code

Can be reassigned a new value or deleted               Cannot be deleted or changed

参考文献

AS3基础知识:功能

每个人都解释了闭包的实际用例:定义和几个例子。

我想贡献一个闭包用例列表:

假设你想计算按钮被点击的次数;封闭是最好的选择。 节流和反弹 局部套用 记住 在异步世界中维护状态 函数就像一次 settimeout 迭代器

我曾经写过一篇关于如何使用闭包来简化事件处理代码的文章。它比较ASP。NET事件处理到客户端jQuery。

http://www.hackification.com/2009/02/20/closures-simplify-event-handling-code/

这里我有一个闭包概念的简单例子,我们可以在我们的电子商务网站或其他许多网站上使用它。

我正在添加示例的JSFiddle链接。它包含一个由三种商品组成的小产品清单和一个购物车柜台。

JSFiddle

// Counter closure implemented function; var CartCouter = function(){ var counter = 0; function changeCounter(val){ counter += val } return { increment: function(){ changeCounter(1); }, decrement: function(){ changeCounter(-1); }, value: function(){ return counter; } } } var cartCount = CartCouter(); function updateCart() { document.getElementById('cartcount').innerHTML = cartCount.value(); } var productlist = document.getElementsByClassName('item'); for(var i = 0; i< productlist.length; i++){ productlist[i].addEventListener('click', function(){ if(this.className.indexOf('selected') < 0){ this.className += " selected"; cartCount.increment(); updateCart(); } else{ this.className = this.className.replace("selected", ""); cartCount.decrement(); updateCart(); } }) } .productslist{ padding: 10px; } ul li{ display: inline-block; padding: 5px; border: 1px solid #DDD; text-align: center; width: 25%; cursor: pointer; } .selected{ background-color: #7CFEF0; color: #333; } .cartdiv{ position: relative; float: right; padding: 5px; box-sizing: border-box; border: 1px solid #F1F1F1; } <div> <h3> Practical use of a JavaScript closure concept/private variable. </h3> <div class="cartdiv"> <span id="cartcount">0</span> </div> <div class="productslist"> <ul> <li class="item">Product 1</li> <li class="item">Product 2</li> <li class="item">Product 3</li> </ul> </div> </div>