有可能在立即调用的函数表达式中调用JavaScript函数吗?

Is It Possible To Call A JavaScript Function Inside An Immediately-Invoked Function Expression

本文关键字:调用 函数 JavaScript 表达式 有可能      更新时间:2023-09-26

我使用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"?

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

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();

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

为您可能希望这样做的其他类或函数创建一个名称空间。你不想一直污染全局命名空间但你也可以创建一个全局命名空间然后把个人的东西放到下面:

(function($){
  window.MyNamespace = function(){};
  var message = "Something here";
  $.extend(MyNamespace, {
    x: function(){
      alert(message);
    }
  });
})(jQuery)
MyNamespace.x()

你可以这样修改你的代码:

<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/

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

var foo = (function(){
    return your_function;
}());

您可以通过使用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模块模式:

  • http://www.adequatelygood.com/2010/3/JavaScript-Module-Pattern-In-Depth

试试这个:

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

闭包的目的之一是限制作用域。这就是为什么x()是定义的,并且可以在立即调用的函数表达式中调用,但在外部是未定义的。

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

var x; //scoped *outside* of the closure
(function ($) {
  var message = 'x called';
  x = function() {
    alert(message);
  }
})(jQuery);
x(); //alerts 'x called'

您可以通过使用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 "访问函数。函数名"例如-

namespaceTestIIFE.testAlert();