HTML属性中事件处理程序内的"this"

3

我曾经认为我很理解"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”的按钮对象

是否有任何解释?

谢谢


https://github.com/getify/You-Dont-Know-JS - t3__rry
据我所知,第一个按钮的onclick是一个执行eval("go()")函数的方法,这会导致go失去上下文并恢复为window作为上下文。这是内联代码不好的众多原因之一。 - user5734311
1个回答

6

简述:

go 并不是第一个按钮的事件处理程序。该事件处理程序是由 HTML 解析器生成的匿名函数。在例子中,生成的处理程序 刚好调用了 go


在 HTML 中提供的 JavaScript 代码用于 onEventName 属性将被编译成以下形式的函数:

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

以这种方式生成的解析器函数具有相当奇怪的作用域链,其中包括生成处理程序的元素、任何外部 form 元素和至少是 document 对象的元素。作用域链的原因可以追溯到 DOM 标准化之前。早期的 IE 版本提供了 window.event 而不是 event 参数。
所以第一个按钮
 <button onclick="go()">clic1</button>

在当前的浏览器中,会生成按钮的onclick处理程序如下:

 function( event) {
     go()
 }
  • the onclick handler is the function taking the event parameter. It is called with a this value of the button.

  • go is an ordinary function call - the this value of the caller has not been applied. You could, say, pass on this as a parameter by calling go(this) if you wanted to.

  • go was declared using the function keyword and by default has a this value of the global object.

  • If you must attach a [myHandler] function in HTML to be called like an event handler, add an attribute in the opening tag like

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

    or provided the this value is not required, simply

    oneventname="myHandler(event);
    
在第二个例子中,您可以正常编译一个匿名函数表达式(不使用HTML解析器),并直接将其附加到第二个按钮元素上。
  • 附加的函数将以按钮作为其this值进行调用,可以记录到控制台。

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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接