【问题标题】:access variable inside anonymous function from outside从外部访问匿名函数内部的变量
【发布时间】:2013-08-16 12:06:08
【问题描述】:

jquery-ui 对话框小部件(就像所有其他小部件一样)被包装在一个匿名函数中。

在这个函数内部有一个声明为sizeRelatedOptions的变量。我需要从包装闭包外部向该对象添加一个键。实现这一目标的最佳方法是什么?

(function( $, undefined ) {

    var sizeRelatedOptions = {
        buttons: true,
        height: true,
        //etc
    }

    $.widget( "ui.dialog", {
        //widget code
    });

}( jQuery ) );

编辑#1:上面的代码是jQuery ui的source code

编辑#2:我现在明白我不能简单地访问该变量。所以我必须解决这个问题。因此,这里有一些关于我为什么需要这个的更多信息:

我正在扩展 jQuery ui 的对话框小部件以添加另一个 buttonPane。为了在将窗格添加到小部件后使小部件自行调整大小,我想向sizeRelatedOption 添加一个选项。 (这就是这个问题首先要解决的问题。)因为对话框小部件的_options 函数会检查sizeRelatedOption 中是否存在该选项作为键。在这种情况下,它会调用 _size 函数来调整小部件的大小。

希望我能说清楚一点。

【问题讨论】:

  • 不能在全局范围内声明变量吗?
  • @JeevanJose 我想修改 jquery 的源代码不是一个好主意!
  • sizeRelatedOptions 来自 jQuery 的源码??
  • @JeevanJose 是的。我已经添加了指向源代码的链接。
  • 每个人似乎都忘记了 OP 不拥有小部件的代码,它是 jQuery UI 库的一部分。修改库的源代码是一种非常糟糕的做法,会导致维护噩梦,因此这里唯一可行的答案是您无法实现这一点。

标签: javascript jquery jquery-ui


【解决方案1】:

您根本无法不直接修改源代码,但这不是您应该考虑的选项,因为出于多种原因,这是一种非常糟糕的做法。

该变量对该范围是私有的,除非该对象使其可以公开访问,否则您的代码必须在声明该变量以访问它的那个范围内或子范围内运行。

但是,如果您尝试更改某些配置选项,小部件已经为此提供了API

例如,

$('#dialog').dialog({
    height: 500,
    width: 500
});

编辑:如果您可以向我们提供更多详细信息,说明您尝试实现这一目标的原因,我们可能会为您提供其他选择。

【讨论】:

  • 您能解释一下否决票吗?这实际上是唯一有效的答案,因为 OP 不拥有代码并且永远不应该修改小部件的代码。
  • 不是我的反对意见,但你错了:OP没有创建原始代码,但这并不意味着他下载后不能修改它。
  • OP 声明的变量是用户定义的。它不是来自api。除了你说,我引用“你根本做不到”。这是错误的,因为在 javascript 中,您可以使用 window.variableName 使变量声明成为全局变量。我希望这可以解释反对意见。
  • @Blazemonger,那么在这种情况下,为什么不修改对象文字并添加新键呢?出于多种原因修改您不拥有的代码是一种非常糟糕的做法,不应将其视为明智的选择。为什么 OP 甚至会问他是否可以直接修改代码?
  • @Blazemonger,我以为他会知道如何使用文本编辑器。无论如何,我已经修改了我的答案并增加了精度。
【解决方案2】:

您可以将其设置为全局变量:

var window.sizeRelatedOptions = { // now it's a global

最好让你的匿名函数返回变量,但是:

var myvar = (function( $, undefined ) {

  var sizeRelatedOptions = {
    buttons: true,
    height: true,
    //etc
  };
  var returnvar = sizeRelatedOptions; // in case sizeRelatedOptions is modified

  $.widget( "ui.dialog", {
      //widget code
  });

  return returnvar;

}( jQuery ) ); // now myvar contains the same data

【讨论】:

  • 如果小部件直接替换 sizeRelatedOptions 而不是更改其属性,例如sizeRelatedOptions = { buttons: false, height: true } 而不是 sizeRelatedOptions.buttons = false;
  • @Sacho True,但如果没有来自 OP 的更多代码,我没有理由期待。添加了一些代码来解决这种可能性。
  • @plalx 当然这是一个选项;它是 JavaScript 代码,它没有被编译。 OP可以随时下载修改。
【解决方案3】:

将窗口对象传递给函数,然后您可以将方法和属性附加到它。

(function( $, window, undefined ) {

    window.sizeRelatedOptions = {
        buttons: true,
        height: true,
        //etc
    }

    $.widget( "ui.dialog", {
        //widget code
    });

}( jQuery, window ) );

【讨论】:

    【解决方案4】:

    你应该在全局范围内声明这个变量。 您可以使用$.extend 向现有对象添加属性。

    window.sizeRelatedOptions  = {};
    
    (function( $, undefined ) {
        $.extend(sizeRelatedOptions ,  {
            buttons: true,
            height: true,
            //etc
        });
    
        $.widget( "ui.dialog", {
            //widget code
        });
    }( jQuery ) );
    

    【讨论】:

      【解决方案5】:
      var accessor = (function( $, undefined ) {
      
          var sizeRelatedOptions = {
              buttons: true,
              height: true,
              //etc
          }
      
          $.widget( "ui.dialog", {
              //widget code
          });
          return {
             getSizeRelatedOptions: function () { return sizeRelatedOptions; }
          }
      }( jQuery ) );
      accessor.getSizeRelatedOptions();
      

      我认为不修改小部件的源是不可能的。

      【讨论】:

      • 为什么不简单地将其作为全局接口的一部分呢?在这种情况下,我认为添加访问器没有任何好处。