JavaScript—用闭包模拟私有方法

来源:互联网 发布:pdf.js如何使用 编辑:程序博客网 时间:2024/04/30 16:02

用闭包模拟私有方法EDIT

诸如 Java 在内的一些语言支持将方法声明为私有的,即它们只能被同一个类中的其它方法所调用。

对此,JavaScript 并不提供原生的支持,但是可以使用闭包模拟私有方法。私有方法不仅仅有利于限制对代码的访问:还提供了管理全局命名空间的强大能力,避免非核心的方法弄乱了代码的公共接口部分。

下面的示例展现了如何使用闭包来定义公共函数,且其可以访问私有函数和变量。这个方式也称为 模块模式(module pattern):

var Counter = (function() {  var privateCounter = 0;  function changeBy(val) {    privateCounter += val;  }  return {    increment: function() {      changeBy(1);    },    decrement: function() {      changeBy(-1);    },    value: function() {      return privateCounter;    }  }   })();console.log(Counter.value()); /* logs 0 */Counter.increment();Counter.increment();console.log(Counter.value()); /* logs 2 */Counter.decrement();console.log(Counter.value()); /* logs 1 */

这里有很多细节。在以往的示例中,每个闭包都有它自己的环境;而这次我们只创建了一个环境,为三个函数所共享:Counter.increment,Counter.decrement 和 Counter.value

该共享环境创建于一个匿名函数体内,该函数一经定义立刻执行。环境中包含两个私有项:名为 privateCounter 的变量和名为 changeBy 的函数。 这两项都无法在匿名函数外部直接访问。必须通过匿名包装器返回的三个公共函数访问。

这三个公共函数是共享同一个环境的闭包。多亏 JavaScript 的词法范围的作用域,它们都可以访问 privateCounter 变量和 changeBy 函数。

您应该注意到了,我们定义了一个匿名函数用于创建计数器,然后直接调用该函数,并将返回值赋给 Counter 变量。也可以将这个函数保存到另一个变量中,以便创建多个计数器。

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 */Counter1.decrement();console.log(Counter1.value()); /* logs 1 */console.log(Counter2.value()); /* logs 0 */

请注意两个计数器是如何维护它们各自的独立性的。每次调用 makeCounter() 函数期间,其环境是不同的。每次调用中, privateCounter 中含有不同的实例。

这种形式的闭包提供了许多通常由面向对象编程U所享有的益处,尤其是数据隐藏和封装。

0 0