Javascript从没有全局范围的元素事件调用函数

时间:2015-04-16 23:41:40

标签: javascript jquery

在外部加载的javascript文件中(使用jQuery)我有:

$(function() {
    function foo() {
        console.log("bar");
    }
}

然而,当我尝试打电话时在HTML中:

<a onclick="foo()">Call foo</a>

这打破Uncaught ReferenceError: foo is not defined

是否可以将实际的函数调用保存在HTML (在a标记上)并使其有效?

5 个答案:

答案 0 :(得分:1)

您可以将它附加到全局窗口对象:

$(function() {
    window.foo = function() {
        console.log("bar");
    }
}

答案 1 :(得分:1)

  

是否可以在HTML中保持实际的函数调用(在a   标签)并让它工作?

没有。要在HTML元素onclick=foo()上使用该方法,则函数foo必须位于全局范围内。

定义不带var关键字的函数将允许它进入全局范围:

$(function() {
   foo = function() { console.log('bar'); }
});

但污染全球范围从来都不好,那为什么不命名呢?

$(function() {
   var ns = 'MYNAMESPACE';
   window[ns] = window[ns] || {}; //create a global namespace
   window[ns].foo = function() { console.log('bar'); }
});

<a href="#" onclick="MYNAMESPACE.foo()">Call foo</a>

答案 2 :(得分:1)

  

是否可以在HTML中保持实际的函数调用(在a   标签)并让它工作?

不,如果您的函数foo不在全局范围内,或者在一些特殊的全局对象中,那么HTML无法找到您的函数,并且您无法在HTML中进行任何更改。作为参考,您的函数foo位于本地范围内,而不是全局范围。因此,为了保持HTML不变,您必须将foo移动到全局范围或移动到少数全局对象之一。

有很多原因导致在HTML中直接嵌入函数调用并不是一个好习惯。一个主要原因是它要求这些功能是全局范围的,这本身并不是一种好的做法。

由于您已经在使用jQuery,因此您只需将代码更改为:

$(function() {
    function foo() {
        console.log("bar");
    }

    $("#callme").click(foo);
}

<a id="callme">Call foo</a>

或者,如果您有多个<a>标记需要相同的点击行为,则可以执行以下操作:

$(function() {
    function foo() {
        console.log("bar");
    }

    $(".callme").click(foo);
}

<a class="callme">Call foo</a>
<a class="callme">Call foo</a>

或者,这些结构中的任何一个都可以使用匿名函数:

$(function() {
    $(".callme").click(function(e) {
        console.log("bar");
    });
}

<a class="callme">Call foo</a>
<a class="callme">Call foo</a>

从实际HTML中删除所有代码引用称为 Unobstrusive Javascript ,被许多人认为是一种很好的做法。你可以在这里阅读这个实践:

What is Unobtrusive JavaScript and Why it’s Important?

Wikipedia - Unobtrusive JavaScript

W3 - The principles of unobtrusive JavaScript

答案 3 :(得分:0)

尝试

window.onerror = function(e) {
  console.log(e)
}

$(function() {

  function foo() {
    console.log("bar");
  }

  (function _foo() {
    return $(this).queue("foo", [function(next) {
      foo(); return next()}, _foo])
  }).call(this);

});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js"></script>
<a onclick="jQuery(document).dequeue('foo')">Call foo</a>

答案 4 :(得分:0)

event handler content attributes的范围是

  • 全球范围
  • 文件
  • form owner(如果有的话)
  • 元素(如果有)

这意味着foo函数必须是其中一个属性才能使用

<a onclick="foo()">Call foo</a>

一些例子:

&#13;
&#13;
(function() {
  window.foo = function() {
    alert("bar");
  }
})();
&#13;
<a onclick="foo()">Call foo</a>
&#13;
&#13;
&#13;

&#13;
&#13;
(function() {
  document.foo = function() {
    alert("bar");
  }
})();
&#13;
<a onclick="foo()">Call foo</a>
&#13;
&#13;
&#13;

&#13;
&#13;
(function() {
  document.querySelector('form').foo = function() {
    alert("bar");
  }
})();
&#13;
<form>
  <button onclick="foo()">Call foo</button>
</form>
&#13;
&#13;
&#13;

&#13;
&#13;
(function() {
  Element.prototype.foo = function() {
    alert("bar");
  }
})();
&#13;
<a onclick="foo()">Call foo</a>
&#13;
&#13;
&#13;

&#13;
&#13;
(function() {
  document.querySelector('a').foo = function() {
    alert("bar");
  }
})();
&#13;
<a onclick="foo()">Call foo</a>
&#13;
&#13;
&#13;

但是,我建议使用event handlers IDL attributes或更好的event listeners