You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何document.body事件处理函数中的this指向全局window对象?

为啥body事件处理里的this指向window,但button的就指向元素本身?

先贴下你提供的代码方便大家对照:

<!DOCTYPE html>
<html>
<head>
    <style type="text/css">
        body { height: 1000px; }
    </style>
    <title>Scroll</title>
</head>
<body>
    <button id="btn">click</button>
    <script type="text/javascript">
        document.body.onscroll = function() {
            alert(this);// displays [object Window], instead of [object HTMLBodyElement]
        };
        document.getElementById('btn').onclick = function() {
            alert(this);// displays [object HTMLButtonElement]
        }
    </script>
</body>
</html>

这事儿本质是浏览器对body元素scroll事件的特殊处理逻辑,跟普通元素的事件绑定规则不一样:

  • 像button这种普通元素,当你直接给onclick赋值函数时,这个函数是由触发事件的元素本身调用的,所以this自然指向这个button——这是DOM事件处理的常规表现,完全符合预期。

  • 但body的scroll事件是个例外:浏览器里真正负责处理页面整体滚动的是window对象,body本身并不会触发scroll事件。当你给document.body.onscroll赋值时,浏览器会偷偷把这个函数代理绑定到window.onscroll上。等页面滚动时,是window在调用这个函数,那this肯定就指向window了。

如果想要让body的滚动事件处理里this指向body元素,有两个简单的解决办法:

  1. 用addEventListener绑定事件,它能正确保留元素的上下文:
document.body.addEventListener('scroll', function() {
    alert(this); // 这会儿就会显示[object HTMLBodyElement]了
});

不过要注意:这种方式只有当body自己有独立滚动条(比如设置了overflow: scroll且内容超出容器)时才会触发。如果是整个页面的滚动,还是得监听window的scroll事件。

  1. 直接在函数里用document.body代替this:
document.body.onscroll = function() {
    alert(document.body); // 直接指定指向body,简单省心
};

总结一下:普通元素的on[event]绑定遵循常规逻辑,但body的onscroll因为浏览器的代理机制,实际是window在触发事件,所以this就跑偏到window了。

内容的提问来源于stack exchange,提问作者marcel

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 07:43:51