用作onclick处理程序的函数运算符和函数声明的行为不同

时间:2018-10-06 12:31:36

标签: javascript scope

我有两个功能:

doSomething = function()  {
    alert(this);
}


var doSomethingElse = function() {
    alert(this);
}

这是我的HTML:

<div id="banner-message">
  <p>Hello World</p>
  <button id='button1' onclick='doSomething()'>Do Something</button>
  <button id='button2' onclick='doSomethingElse()'>Do Something Else</button>
</div>

为什么doSomething()函数调用不起作用,而doSomethingElse()不起作用?

https://jsfiddle.net/brjdp56t/

2 个答案:

答案 0 :(得分:2)

有细微的差别。这将在全局范围内创建doSomething

doSomething = function()

这将在当前范围内创建doSomething

var doSomething = function()

后者之所以不起作用,是因为您正在范围内(闭包,window.onload = function() {}$(function() {})等)内执行此代码,因此该变量在范围外不可用。在小提琴中,JavaScript代码包装在window.onload = function() { var doSomethingElse = ... }中。

答案 1 :(得分:2)

  

为什么doSomething()函数调用起作用而doSomethingElse()不起作用?

仅当您显示的代码不在全局范围内时,这才是正确的(提琴中的代码包装在jsFiddle本身提供的onload处理程序中,请参见JavaScript窗格上的选项-这是jsFiddle更为荒谬 令人惊讶的默认选项之一)。原因是我所说的The Horror of Implicit Globals。通过不在此代码中声明doSomething

doSomething = function()  {
        alert(this);
}

...您正在创建一个名为doSomething global 变量。但是,通过在此代码中声明doSomethingElse

var doSomethingElse = function() {
    alert(this);
}

...您正在该代码存在的范围内创建一个 local 变量。

为什么重要?因为您在旧的onXYZ属性样式事件处理程序中调用的任何函数都必须是全局函数。

相反:

  1. 使用严格模式("use strict"),以便将其分配给未声明的标识符是错误的,而不是创建自动全局标识符。

  2. 使用现代事件处理(addEventListener等),而不是需要全局函数的onXYZ属性类型的事件处理程序。

  3. script标记放在文档正文的末尾,即</body>结束标记的前面,以便在代码运行之前创建HTML定义的所有元素。 (然后,您不需要onload或类似的处理程序。)

例如(堆栈片段为您在script的末尾放置自动body标签):

"use strict";
// Scoping function to avoid creating globals
(function() {
    var doSomething = function()  {
        console.log("doSomething");
    };

    var doSomethingElse = function() {
        console.log("doSomethingElse");
    };
    
    document.getElementById("button1").addEventListener("click", doSomething);
    document.getElementById("button2").addEventListener("click", doSomethingElse);
})();
<div id="banner-message">
  <p>Hello World</p>
  <button id='button1'>Do Something</button>
  <button id='button2'>Do Something Else</button>
</div>