【问题标题】:function inside of IIFE not recognizedIIFE 内部的功能无法识别
【发布时间】:2015-05-15 02:53:46
【问题描述】:

我有一个 IIFE,我正在尝试将其制作成一个小书签。我想让小书签弹出的模式有一些按钮可以调用一个函数。但是,当我有这样的结构时:

(function(){

   var __myFn = function(str){ //also have tried function __myFn(){..}
      alert(str);
   }

   //some AJAX that builds HTML with the `result`s

   document.getElementById("resultDiv").innerHTML = "<span onclick='__myFn(" + result.someData+ ")'>test</span>


}());

我收到Uncaught ReferenceError: __myFn is not defined

我怎样才能让这个功能被识别?还有其他方法吗?

【问题讨论】:

  • span 元素在全局范围内,__myFn() 在 IIFE 范围内。您可以使用适当的 DOM 操作方法和 addEventListener 来附加事件。
  • 是的,但我不确定如何在没有库的情况下进行事件委托,我想我会这样做,因为这些跨度在加载时不在页面上。我认为可能有更简单的方法。
  • 委托?你可以做到on a newly-created element。如果您从 AJAX 获取数据,则必须在回调函数中执行此操作。
  • @Teemu 非常好。谢谢你的想法!

标签: javascript ajax closures iife


【解决方案1】:

当您使用var 关键字时,您正在创建一个位于封闭上下文范围内的变量。由于封闭上下文是一个函数,__myFn 是函数本身的局部变量,并且在外部不知道(即,在全局上下文中不知道)。

如果你想使用里面的东西,你必须返回一个对它的引用。你可以使用类似模块模式的东西:

var myModule = (function(){

   var __myFn = function(str) { 
      alert(str);
   }

   return {
       myFn: __myFn
   };

})();

那么你可以这样做:

//some AJAX that builds HTML with the `result`s

document.getElementById("resultDiv").innerHTML = "<span onclick='myModule.myFn(" + result.someData+ ")'>test</span>

但是,我建议不要以这种方式绑定您的事件处理程序。使用 jQuery 或使用 DOM 方法 (addEventListener) 来绑定事件处理程序。通过这种方式,您甚至可以在 IIFE 内部执行此操作,这意味着您甚至不必从 IIFE 返回任何东西。这意味着您的全局上下文没有受到污染。现在,您必须从 IIFE 返回某些内容的唯一原因是因为您通过 HTML 内联绑定事件处理程序。

这里有两个例子。第一个假设 IIFE 返回对__myFn 的引用:

var resultDiv = document.getElementById("resultDiv");
resultDiv.addEventListener("click", myModule.myFn, false);

这是第二个在 IIFE 内部执行此操作的示例:

(function(){

   var __myFn = function(str) { 
      alert(str);
   }

   var resultDiv = document.getElementById("resultDiv");
   resultDiv.addEventListener("click", __myFn, false);

})();

【讨论】:

  • 你能举一个正确的事件绑定的例子吗?
  • @Bergi 我添加了一个示例。
  • 非常感谢。我还有几个问题。如果元素是通过 ajax 加载并且在加载脚本时不在页面上,如何绑定事件?此外,在第一个示例中,如何扩展它以支持多种功能。我试过return {myFn: __myFn, myFn2: myFn2};,但它打破了错误undefined is not a function
【解决方案2】:

由于我不明白的原因,我发现从声明中删除“var”可以使其工作。

示例 1(失败):

(function() {

    var counter = 0;
    var init = function() { console.log("init called"); }
})();

init(); // regardless of whether I named the function or not, this fails.

但是: 示例 2(有效):

(function() {
    var counter = 0;
    init = function() { console.log("init called"); }
})();

init(); // this calls the function just fine.

请注意,您可以通过这种方式在 iife 中添加任意数量的函数。

【讨论】:

  • 这是因为如果没有var,您将在全局范围内创建/修改init,这就是稍后可以访问它的原因。这不是很好的做法。最好只返回关闭,这就是为什么 Vivin Paliath 的答案更可取的原因。
猜你喜欢
  • 1970-01-01
  • 2021-01-06
  • 2020-08-06
  • 1970-01-01
  • 1970-01-01
  • 2021-01-22
  • 2019-08-01
  • 2011-10-01
  • 1970-01-01
相关资源
最近更新 更多