HTML 属性事件处理程序中的“this”

"this" inside event handler from HTML attribute

提问人:AntonBoarf 提问时间:6/7/2018 最后编辑:decezeAntonBoarf 更新时间:8/26/2022 访问量:440

问:

我以为我理解了“this”关键字,直到我看到这段代码:

<body>
    <button onclick="go()">clic1</button>

    <button id="btn">clic2</button>

    <script>

        function go() {
            console.log(this);
        }

        var btn = document.getElementById("btn");
        btn.onclick = function() {
            console.log(this)
        }

    </script>
</body>

我有一个带有两个按钮的 HTML 文档,它们在单击时执行相同的操作:它们记录“this”关键字。

我很惊讶他们没有显示相同的结果:

对于按钮 “clic1” : this = Window

对于按钮 “clic2” : this = id 为 “btn” 的按钮对象

对此有什么解释吗?

谢谢

javascript 处理程序

评论

0赞 t3__rry 6/7/2018
github.com/getify/You-Dont-Know-JS
0赞 6/7/2018
Afaik,第一个按钮的 onclick 是一个函数,它会导致丢失上下文并恢复为上下文。这是内联代码不好的众多原因之一。eval("go()")gowindow

答:

6赞 traktor 6/7/2018 #1

顶级域名:

go不是第一个按钮的事件处理程序。事件处理程序是由 HTML 解析器生成的匿名函数。在此示例中,生成的处理程序恰好调用 .go


HTML 中为属性提供的 JavaScript 代码被编译为表单函数onEventName

function(event) {
    // code written in the attribute value
}

解析器以这种方式生成的函数具有一个相当奇怪的作用域链,其中包括生成的处理程序是其属性的元素、元素所在的任何外部表单元素以及文档对象。作用域链的原因可以追溯到 DOM 标准化之前。较旧的 IE 版本提供了 window.event 而不是 event 参数。

所以第一个按钮

 <button onclick="go()">clic1</button>

在当前浏览器中,将按钮的 onClick 处理程序生成为:

 function( event) {
     go()
 }
  • onclick 处理程序是采用参数的函数。它使用按钮的值进行调用。eventthis

  • go是普通函数调用 - 调用方的值尚未应用。比如说,如果你愿意,你可以通过调用来传递参数。thisthisgo(this)

  • go使用关键字声明,默认情况下具有全局对象的值。functionthis

  • 如果必须在 HTML 中附加一个 [] 函数才能像事件处理程序一样调用,请在开始标记中添加一个属性,例如myHandler

    oneventname = "myHandler.call(this, event)"
    

    或者,如果 this 值不是必需的,只需

    oneventname="myHandler(event);
    

在第二个示例中,您正常编译一个匿名函数表达式(不使用 HTML 解析器),并将其直接附加到第二个按钮元素。

  • 调用附加函数时,按钮作为其值,可以记录到控制台。this

  • 附加的函数没有 Wierdo 作用域链。