为什么不能删除从DOM自动生成的Javascript变量?

Geo*_*pty 5 javascript dom javascript-objects

它可能不是常识,但"许多(所有?)现代浏览器上的Javascript似乎在具有ID"的DOM元素的窗口对象上创建变量.

知道了这一点,我希望能够删除这些变量,下面是我试过但没有成功的一些代码.还要考虑我的console.log语句的屏幕截图,它首先表明why它不是窗口的属性(它应该介于"webkitUrl"和"window"之间),但是在紧跟第一个之后的两个console.log语句中,窗口/为什么显示为文档中的div?

为什么这些自动生成的变量不能从其父对象中删除,就像其他任何变量一样?

<!DOCTYPE html>

<html>
<head>
    <script>
    setTimeout(function() { //poor man's document/ready
        var allElements = document.getElementsByTagName("*"), elementId;

        for (var i=allElements.length; i--; ) {
            elementId = allElements[i].id;

            if (elementId && window[elementId] instanceof HTMLElement) {
                delete window.why;
                console.log(window);
                console.log(window.why);
                console.log(why);
            }
        }
    });
    </script>
</head>

<body>
<div id="why"></div>
</body>

</html>
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

Ori*_*iol 5

那是因为这些属性不是直接存储的window.相反,它的行为就像一个代理.

例如,查看Firefox在使用getOwnPropertyDescriptor时执行的操作WindowProperties(从中window继承):

bool WindowNamedPropertiesHandler::getOwnPropDescriptor(
  JSContext* aCx, JS::Handle<JSObject*> aProxy, JS::Handle<jsid> aId,
  bool /* unused */, JS::MutableHandle<JS::PropertyDescriptor> aDesc
) const {
  // ...
  Element* element = document->GetElementById(str);
  if (element) {
    JS::Rooted<JS::Value> v(aCx);
    if (!WrapObject(aCx, element, &v)) {
      return false;
    }
    FillPropertyDescriptor(aDesc, aProxy, 0, v);
    return true;
  }
  // ...
}
Run Code Online (Sandbox Code Playgroud)

您可能会认为,当您将ID设置为某个元素时,Firefox会将其存储为全局属性.但它不能像这样工作:当你试图访问Firefox将GetElementById用来知道是否有一个具有该ID的元素时,并且相应地回答.

更重要的是,明确禁止删除:

bool WindowNamedPropertiesHandler::delete_(
  JSContext* aCx, JS::Handle<JSObject*> aProxy,
  JS::Handle<jsid> aId, JS::ObjectOpResult &aResult
) const {
  return aResult.failCantDeleteWindowNamedProperty();
}
Run Code Online (Sandbox Code Playgroud)

此行为是硬编码的,您无法阻止它.因此,如果这些属性惹恼了您,只需通过声明自己的变量来覆盖它们.