全局名称空间和onclick函数的污染

时间:2018-10-26 09:29:53

标签: javascript html

假设代码

//(function() {
  function addItem() {
    alert("item added!");
  }
//})();
<button onclick="addItem()">add item</button>

如果我将不污染全局名称空间,并且将注释的代码取消注释,那么我的功能将被破坏...

对于此类问题,通常的解决方法是什么,将html内联保持“ on ...”事件处理程序?


PS。作为初学者的注意事项:

经验丰富的开发人员可能会建议您避免使用内联onclick属性。不使用它们的原因有很多:

  • 表达与行为之间的紧密耦合;
  • 代码(通常)在全局范围内运行;
  • 使测试和调试变得困难;
  • 无视渐进增强;
  • 很快变得难以维护;
  • 它还将取消绑定任何先前分配的单击处理程序,这可能是有害的副作用;

3 个答案:

答案 0 :(得分:4)

您要在这里closure

var myGlobalClosure = (function(){
     var myPrivateVariable = "item added from inside closure!";
     function addItem() {
        alert(myPrivateVariable);
     }
    
    return {addItem:addItem};
})();

//if I have variable collisions they don't affect my closed over code.
//so this illustrates one of the big advantages of this pattern
var myPrivateVariable = "this is in the global scope and won't do anything";
<button onclick="myGlobalClosure.addItem()">add item</button>

上述闭包是revealing module pattern的示例。这是一种常见的JS结构设计模式。

最终,某些东西必须在全局范围内,否则您将无法引用它。这里的想法是组织全局对象,使其具有结构。这还将防止与标准功能/对象名称(例如click等)发生冲突。

这是大多数库构造其代码的方式,例如jQuery / $是一个封闭jQuery函数和对象的闭包。

答案 1 :(得分:2)

使用EventTarget.addEventListener()通过 JS 使用事件绑定代替内联事件。

(function() {
  var add_btn = document.getElementById('add_btn');

  function addItem() {
    alert("item added!");
  }
  add_btn.addEventListener('click', addItem);
})();
<button id="add_btn">add item</button>

答案 2 :(得分:0)

如果您确实需要保留内联onclick属性,另一种解决方案是将整个事件处理程序代码放在此处:

<button onclick="
void function () {
    function addItem() {
        alert('item added');
    }
    addItem();
}()
">add item</button>


您还可以将该函数存储在button元素本身中,然后在onclick处理程序中查找该函数:

document.getElementById('add_butt').addItem = function () {
    alert("item added");
};
<button id="add_butt" onclick="this.addItem()">add item</button>