为什么匿名函数中的私有变量可以从javascript中的函数外部访问?

时间:2014-12-30 01:29:51

标签: javascript

在阅读了一本“Essential JS Design Patterns”一书之后,我无法理解这段代码中私有变量的行为:

var SingletonTester = (function () {

  // options: an object containing configuration options for the singleton
  // e.g var options = { name: "test", pointX: 5};
  function Singleton( options )  {

    // set options to the options supplied
    // or an empty object if none are provided
    options = options || {};

    // set some properties for our singleton
    this.name = "SingletonTester";

    this.pointX = options.pointX || 6;

    this.pointY = options.pointY || 10;

  }

  // our instance holder
  var instance;

  // an emulation of static variables and methods
  var _static  = {

    name:  "SingletonTester",

    // Method for getting an instance. It returns
    // a singleton instance of a singleton object
    getInstance:  function( options ) {
      if( instance  ===  undefined )  {
        instance = new Singleton( options );
      }

      return  instance;

    }
  };

  return  _static;

})();

var singletonTest  =  SingletonTester.getInstance({
  pointX:  5
});

// Log the output of pointX just to verify it is correct
// Outputs: 5
console.log( singletonTest.pointX );

这是一本关于Singleton模式的书的例子 有一个匿名函数,它返回一个包含“name”成员的对象和用于返回“Singleton”函数实例的“getInstance”方法。
我的麻烦是了解SingletonTester中存储的对象如何访问“实例”私有var。我的意思是,在匿名函数完成其工作之后,SingletonTester变量应仅包含对象:

{
    name:  "SingletonTester",

    // Method for getting an instance. It returns
    // a singleton instance of a singleton object
    getInstance:  function( options ) {
      if( instance  ===  undefined )  {
        instance = new Singleton( options );
 }

并且此对象不知道实例是什么。 “Singleton”函数的实例化也是一样的。它是如何知道什么函数是“Singleton”,它是在匿名函数的范围内定义的?

1 个答案:

答案 0 :(得分:1)

您遇到的是JavaScript中的词法范围。基本上,无论何时执行函数,您都可以访问该函数的作用域。除此之外,您还可以访问定义函数的词法范围。

我们来看一个例子:

var someObject = (function () {
  var privateVariable = 18;

  var getValue = function () {
    return privateVariable;
  };

  return {
    getValue: getValue
  };
})();

对象'someObject'有一个方法'getValue',它在执行时返回值18.但这怎么可能?以下是尝试执行someObject.getValue()时JavaScript引擎的工作原理:

  1. JavaScript引擎对someObject对象执行属性查找,并发现它有自己的getValue属性。
  2. 一旦它找到了函数对象(getValue),它就会执行函数。
  3. 当函数执行时,JavaScript引擎会尝试查找privateVariable的值。
  4. 但是,在'getValue'函数的范围内,privateVariable不存在。
  5. 因此,JavaScript引擎会查看PARENT范围(即声明getValue函数的范围)。
  6. 此范围对应于匿名函数的范围。在此范围内,privateVariable的值为18.
  7. 这是JavaScript中的词汇范围。关于您的示例,这就是SingletonTester实例可以访问“实例”变量的原因。

    我强烈建议您阅读本书以了解更多信息:Scope and Closures