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

为何将函数名当作对象使用?修改后函数转为构造函数的原因

关于Element.scrollHeight学习中的两个问题

我在学习Element.scrollHeight时遇到两个无法理解的问题,先贴出相关原代码:

function checkReading () {
  if (checkReading.read) {
    return;
  }
  checkReading.read = this.scrollHeight - Math.round(this.scrollTop) === this.clientHeight;
  document.registration.accept.disabled = document.getElementById("nextstep").disabled = !checkReading.read;
  checkReading.noticeBox.textContent = checkReading.read ? "Thank you." : "Please, scroll and read the following text.";
}

onload = () => {
  const oToBeRead = document.getElementById("rules");
  checkReading.noticeBox = document.createElement("span");
  document.registration.accept.checked = false;
  checkReading.noticeBox.id = "notice";
  oToBeRead.parentNode.insertBefore(checkReading.noticeBox, oToBeRead);
  oToBeRead.parentNode.insertBefore(document.createElement("br"), oToBeRead);
  oToBeRead.onscroll = checkReading;
  checkReading.call(oToBeRead);
}

问题列表

  • 为什么要将checkReading(函数名)当作对象/变量来使用?
  • 我尝试移除checkReading相关引用,改用oToBeRead对象作为this,编写了this.read = this.scrollHeight - Math.round(this.scrollTop) === this.clientHeight这段代码后,checkReading函数被识别为构造函数,这是为什么?

以下是我修改后的代码:

function checkReading () {
  if (checkReading.read) {
    return;
  }
  this.read = this.scrollHeight - Math.round(this.scrollTop) === this.clientHeight;
  document.registration.accept.disabled = document.getElementById("nextstep").disabled = !this.read;
  this.noticeBox.textContent = checkReading.read ? "Thank you." : "Please, scroll and read the following text.";
}

onload = () => {
  const oToBeRead = document.getElementById("rules");
  oToBeRead.noticeBox = document.createElement("span");
  document.registration.accept.checked = false;
  oToBeRead.noticeBox.id = "notice";
  oToBeRead.parentNode.insertBefore(checkReading.noticeBox, oToBeRead);
  oToBeRead.parentNode.insertBefore(document.createElement("br"), oToBeRead);
  oToBeRead.onscroll = checkReading;
  checkReading.call(oToBeRead);
}

Quokka提示函数被识别为构造函数
该图片显示函数被转换为构造函数,Quokka工具提示将其修改为类声明。


问题解答

  1. 为什么把checkReading当作对象使用?
    在JavaScript里,函数本身就是Function类型的对象,天然支持添加自定义属性。原代码里这么做,是把函数checkReading当成了一个小型的命名空间——用它来存储全局状态(read标记用户是否读完内容)和DOM元素(noticeBox提示框),这样可以避免声明额外的全局变量,减少全局作用域的污染,同时让相关的状态和逻辑集中在一起,更易维护。

  2. 为什么修改后函数被识别为构造函数?
    Quokka这类工具是通过静态代码分析来判断代码意图的:当函数内部出现this.xxx = ...这样的属性赋值操作时,工具会默认认为你可能是想把这个函数当作构造函数(也就是用new关键字调用、创建实例的函数),所以会提示你改成类声明。但实际上你是通过checkReading.call(oToBeRead)把this绑定到了DOM元素oToBeRead上,属于显式指定上下文,只是工具的静态分析没识别到这一点,产生了误判。

另外注意你修改后的代码存在逻辑错误:比如oToBeRead.parentNode.insertBefore(checkReading.noticeBox, oToBeRead)这里,你已经把noticeBox挂到了oToBeRead上,应该改成oToBeRead.noticeBox;还有this.noticeBox.textContent = checkReading.read ? ...里的checkReading.read也应该改成this.read,否则会读取错误的状态值。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 00:10:40