我可以命名一个JavaScript函数并立即执行它?

内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用

  • 回答 (2)
  • 关注 (0)
  • 查看 (23)

我有很多这样的:

function addEventsAndStuff() {
  // bla bla
}
addEventsAndStuff();

function sendStuffToServer() {
  // send stuff
  // get HTML in response
  // replace DOM
  // add events:
  addEventsAndStuff();
}

重新添加事件是必要的,因为DOM已经改变,所以之前附加的事件不见了。由于它们最初也必须附加(duh),所以它们处于干燥的很好的功能。

这个设置没有问题(或者是否存在?),但我可以平滑一点吗?我想创建该addEventsAndStuff函数并立即调用它,所以它看起来不像是一个非常有趣的东西。

以下两种语法错误都会响应:

function addEventsAndStuff() {
  alert('oele');
}();

(function addEventsAndStuff() {
  alert('oele');
})();
提问于
用户回答回答于

在问题中发布的示例没有任何问题。另一种做法可能看起来很奇怪,但是:

var addEventsAndStuff;
(addEventsAndStuff = function(){
    // add events, and ... stuff
})();

有两种方法可以在JavaScript中定义一个函数。函数声明:

function foo(){ ... }

和一个函数表达式,它是定义除上述以外的函数的任何方式:

var foo = function(){};
(function(){})();
var foo = {bar : function(){}};

函数表达式可以被命名,但是它们的名字不会传播到包含范围。这个代码的含义是有效的:

(function foo(){
   foo(); // recursion for some reason
}());

但这不是:

(function foo(){
    ...
}());
foo(); // foo does not exist

因此,为了命名你的函数并立即调用它,你需要定义一个局部变量,将它作为表达式分配给它,然后调用它。

用户回答回答于

这个设置没有问题(或者是否存在?),但我可以平滑一点吗?

请看看使用事件委派。这就是您实际观察容器上的事件并不会消失的地方,然后使用event.target(或event.srcElement在IE上)找出事件实际发生的位置并正确处理它。

这样,您只需附加一次处理程序,即使您更换内容,他们也会继续工作。

以下是不使用任何帮助器库的事件委派的示例:

(function() {
  var handlers = {};

  if (document.body.addEventListener) {
    document.body.addEventListener('click', handleBodyClick, false);
  }
  else if (document.body.attachEvent) {
    document.body.attachEvent('onclick', handleBodyClick);
  }
  else {
    document.body.onclick = handleBodyClick;
  }

  handlers.button1 = function() {
    display("Button One clicked");
    return false;
  };
  handlers.button2 = function() {
    display("Button Two clicked");
    return false;
  };
  handlers.outerDiv = function() {
    display("Outer div clicked");
    return false;
  };
  handlers.innerDiv1 = function() {
    display("Inner div 1 clicked, not cancelling event");
  };
  handlers.innerDiv2 = function() {
    display("Inner div 2 clicked, cancelling event");
    return false;
  };

  function handleBodyClick(event) {
    var target, handler;

    event = event || window.event;
    target = event.target || event.srcElement;

    while (target && target !== this) {
      if (target.id) {
        handler = handlers[target.id];
        if (handler) {
          if (handler.call(this, event) === false) {
            if (event.preventDefault) {
              event.preventDefault();
            }
            return false;
          }
        }
      }
      else if (target.tagName === "P") {
        display("You clicked the message '" + target.innerHTML + "'");
      }
      target = target.parentNode;
    }
  }

  function display(msg) {
    var p = document.createElement('p');
    p.innerHTML = msg;
    document.body.appendChild(p);
  }

})();

现场示例

请注意,如果单击动态添加到页面的消息,即使没有代码可以在要添加的新段落上钩住事件,也会注册并处理您的点击。还要注意你的处理程序只是地图中的条目,并且你有一个处理程序document.body来完成所有的调度。现在,您可能会将其定位在更有针对性的目标上document.body,但您明白了。此外,在上面我们基本上是派遣id,但你可以做你喜欢的复杂或简单的匹配。

现代JavaScript库,如jQueryPrototypeYUIClosure其他任何应用程序都应提供事件委托功能,以平滑浏览器差异并干净地处理边缘案例。jQuery的当然不会,既有其livedelegate功能,允许您使用全套的CSS3选择器(然后一些)的指定处理。

例如,下面是使用jQuery的等效代码(除非我确定jQuery处理边缘情况,上面的非原创版本没有):

(function($) {

  $("#button1").live('click', function() {
    display("Button One clicked");
    return false;
  });
  $("#button2").live('click', function() {
    display("Button Two clicked");
    return false;
  });
  $("#outerDiv").live('click', function() {
    display("Outer div clicked");
    return false;
  });
  $("#innerDiv1").live('click', function() {
    display("Inner div 1 clicked, not cancelling event");
  });
  $("#innerDiv2").live('click', function() {
    display("Inner div 2 clicked, cancelling event");
    return false;
  });
  $("p").live('click', function() {
    display("You clicked the message '" + this.innerHTML + "'");
  });

  function display(msg) {
    $("<p>").html(msg).appendTo(document.body);
  }

})(jQuery);

扫码关注云+社区