8

我正在使用 jQuery,并在立即调用的函数表达式中包装了一个函数,如下所示:

<script type="text/javascript" src="jquery-1.8.3.min.js"></script>
<script type="text/javascript">
    (function ($) {

        var message = 'x called';

        function x() {
            alert(message);
        }
    })(jQuery);

    x();
</script>

这将导致错误,因为函数“x”未在立即调用的函数表达式之外定义。有没有办法在立即调用的函数表达式之外调用函数“x”?

4

8 回答 8

9

仅当您以某种方式公开该功能时。例如,您可以从外部函数返回它:

var x = (function ($) {

    var message = 'x called';

    function x() {
        alert(message);
    }

    return x;
})(jQuery);

x();

或者,类似地,您可以在对象上返回它:

var obj = (function ($) {

    var message = 'x called';

    function x() {
        alert(message);
    }

    return {"x": x};
})(jQuery);

obj.x();

函数内部声明的函数和变量不能从该函数外部直接访问,除非您通过返回某些内容或提供对该函数外部声明的变量的引用来提供某种访问它们的方法。

于 2013-01-09T20:21:19.880 回答
5

为您可能想要使用的其他类或函数创建一个命名空间。您不想不断地污染全局命名空间,但没有理由不能创建一个全局命名空间并将您的个人事物置于其之下:

(function($){
  window.MyNamespace = function(){};
  var message = "Something here";

  $.extend(MyNamespace, {
    x: function(){
      alert(message);
    }
  });
})(jQuery)

MyNamespace.x()
于 2013-01-09T20:27:11.667 回答
2

您可以按如下方式更改代码:

<script type="text/javascript" src="jquery-1.8.3.min.js"></script>
<script type="text/javascript">
    var x;
    (function ($) {

        var message = 'x called';

        x = function () {
            alert(message);
        }
    })(jQuery);

    x();
</script>

jsFiddle 链接:http: //jsfiddle.net/aLnbn/

于 2013-01-09T20:20:12.803 回答
1

是的,(一种方法是:)只需使用 return 语句从 IIFE 返回,您还需要通过将变量分配给 IIFE 来“捕获”返回

var foo = (function(){

    return your_function;

}());
于 2013-01-09T20:20:29.587 回答
1

您可以通过使用 IIFE 返回(或扩充)全局变量来访问您的方法。

你可以这样做:

var globalObject = (function (theObject, $) {

        if (theObject.theMethod) {
            return theObject;
        }

        var message = 'theMethod called';

        theObject.theMethod = function () {
            alert(message);
        };

        return theObject;

})(globalObject || {}, jQuery);


globalObject.theMethod();

我们使用的模式稍微好一点。

我们有一个全局对象(即命名空间),我们通过导入包含 IIFE 的 js 文件向其中添加模块。

每个 IIFE 都会向单个全局对象添加一个新模块。

这使得我们的整个项目只有一个全局对象,可以通过包含一个文件来选择使用我们的任何模块。

我建议查看这篇文章,这是关于 JavaScript 模块模式的一个很好的讨论:

于 2013-01-09T20:31:47.983 回答
0

试试这个:

var miFunc = (function($) {
    var message = 'x called';
    function x() {
        console.log(message);
    }
    this.x = x;
    return this;
})(jQuery);
miFunc.x();

测试:http: //jsbin.com/erucix/2/edit

于 2013-01-09T20:30:06.887 回答
0

闭包的目的之一是限制范围。这就是为什么x()定义并且可以在您立即调用的函数表达式内部调用但在外部未定义的原因。

要让您的代码在不重构的情况下工作,您可以利用区分函数语句函数运算符的 JS 语法。两者在语义上是相同的,但后者可以分配给适合您的场景的变量:

var x; //scoped *outside* of the closure
(function ($) {
  var message = 'x called';
  x = function() {
    alert(message);
  }
})(jQuery);
x(); //alerts 'x called'
于 2013-01-09T22:34:09.563 回答
0

您可以通过使用 IIFE 返回全局变量来访问您的方法。

//IIFEs - Immediately Invoked Function Expressions
var namespaceTestIIFE = (function ($) {

    /** Public functions and state. */
    var pub = {};

    $(document).ready(function () {
        //your on ready logic
    });

    pub.testAlert = function () {
       alert('Hello TestAlert');
    }
    return pub;
})(jQuery);

或者

var compareForm = (function ()
{
        /** Public functions and state. */
        var pub = {};
        pub.testAlert = function () {
           alert('Hello TestAlert');
        }
    return pub;
}());

要访问函数,请使用“namespace.functionname”,例如 -

namespaceTestIIFE.testAlert();
于 2018-03-30T11:24:11.117 回答