【问题标题】:Learning JavaScript variable scope and object instantiation学习 JavaScript 变量作用域和对象实例化
【发布时间】:2009-12-18 00:10:09
【问题描述】:
var foo = (function() {
    var proxy = {},
        warning = false;

    proxy.warn = function(msg) {
        if (!warning) {
            warning = true;
            alert(msg);
        }
        return this; //For the purpose of method chaining we return proxy object.
    }

    function func() {
        alert(warning); //This is a private function relative to foo.
    }

    return proxy;
}());

foo.warn(); //will alert
foo.warn(); //will not alert since warning has been set to true

我对这里的实例化感到困惑,因为没有使用 new 关键字谁持有警告值?就范围警告而言,这里是否有任何泄漏。

谢谢。

【问题讨论】:

    标签: javascript scope instantiation anonymous-function


    【解决方案1】:

    a住顶闭函数function() {...

    foo 持有您返回的代理对象,这意味着不在此代理对象中的所有内容都是私有的,无法从 foo 访问。如果你想得到a 的值,你可以添加一个返回a =>

    的新函数
    proxy.getValueOfA=function(){return a}
    

    那你可以拨打foo.getValueOfA()

    备注:

    var proxy={}
    

    var proxy=new Object()的缩写形式,所以有一个实例化。

    【讨论】:

    • var proxy = {} 代码使用了一种叫做紧凑对象表示法的东西。这是一个快捷方式,不需要在任何地方使用new 来创建对象。
    • 正如 Joel Coehoorn 所说,{} 等同于 new Object(),因为 [] 等同于 new Array()
    【解决方案2】:

    proxy.methodfunc 都可以通过closure property 访问a。有关范围和对象的更多信息,请查看最近出现的这篇文章: A Concise, Executable Guide to JavaScript Objects, Variables, Functions, and Prototypes

    您发布的代码符合所谓的“module pattern”,并且正在成为一种在 JavaScript 中定义对象的非常流行的方式,因为它使私有变量和方法易于创建(通过利用闭包属性如前所述)。

    【讨论】:

      【解决方案3】:

      这个对另一个问题的回答确实帮助我扩展了对 javascript 对象如何工作的理解:

      JavaScript function aliasing doesn't seem to work

      至于您的代码 sn-p,让我们分解一下。首先查看高层结构:var foo = ( exrpession );。你可以很容易地说:var foo = expression;,但是 IIRC 需要括号来处理特定于 IE 的怪癖。

      现在,在这种情况下,表达式是一个匿名函数。 Javascript 非常适合您定义一个没有名称的函数。除非您在某处保存参考,否则不要期望调用它。您也可以在声明后立即调用匿名函数,如下所示:

      function() {
           alert('test');
           return 42;
      }();
      

      这应该看起来与您的代码 sn-p 中用于 表达式 的基本结构非常相似。希望您可以很容易地看到我的示例中的42 可以很容易地成为一个对象。

      所以问题仍然存在,您为什么要这样做?请记住,在 javascript 中,函数也是对象。作为 OOP 的好学生,您可能希望将对象的某些成员设为私有。但是,javascript 没有任何内置功能来支持这一点。幸运的是,如果您从该内部函数返回一个对象,它将可以访问该函数中定义的其他变量,但外部代码将无法访问它们。因此,您实际上已经创建了一个具有私有成员的对象。

      【讨论】:

      • @Joel:我更新了代码以说明为什么在我的情况下需要这样一个私有变量。谢谢。
      【解决方案4】:

      这个

          return proxy;
      }());
      

      应该是这样的

          return proxy;
      })();
      

      还有这个

      function() {
           alert('test');
           return 42;
      }();
      

      不起作用...语法错误。你应该先试试你的代码,然后再把它放在这里。很确定你是这个意思:

      (function() {
           alert('test');
           return 42;
      })();
      

      另外,你返回一个私有成员的事实破坏了范围关闭的全部意义,但它会起作用......

      var foo = (function() {
          var proxy = {}, // private
          proxy.warn = function(msg) {
          ...
          return proxy; // publicly accessible
      

      和这个一样

      var foo = { warn: function(){ /* code */ } };
      

      【讨论】:

      • @Dan:你为什么说“击败了范围关闭的全部点”,我想持有一个私人开关,以便应该触发警报。
      • 是的,你是对的,这会做到这一点。也许我没有调查你想要做什么,只是你是怎么做的。无论哪种方式,匿名函数中的 var 都是私有的,因此只能由公共或受保护的成员访问。我习惯于在 return 语句中返回我的公共成员(这样你就可以在视觉上/逻辑上分离你的私有/受保护成员。window.foo = (function(){ var warning = true; return( { warn: function( msg ) { return(warning ? alert(msg) : this ); } } ); })();
      最近更新 更多