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

时间:2016-07-05 17:54:34

标签: javascript dom javascript-objects

这可能不是常识,但"Javascript on many (all?) modern browsers seems to create variables on the window object for DOM elements with IDs"

知道这一点我希望能够删除这些变量,以下是我尝试过的一些代码但没有成功。还要考虑我的console.log语句的屏幕截图,它首先表明why不是窗口的属性(它应该介于" webkitUrl"和#34; 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>

enter image description here

2 个答案:

答案 0 :(得分:5)

那是因为这些属性没有直接存储在window中。相反,它的行为就像代理。

例如,当您getOwnPropertyDescriptor WindowProperties继承window时,请参阅what Firefox does

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;
  }
  // ...
}

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

更进一步,明确禁止deletions

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

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

答案 1 :(得分:4)

  

我希望能够删除这些变量

绝对没有理由这样做。这些全局变量are there for backwards compatibility和浏览器几乎不会删除它们。但是,它们是以某种方式创建的,因此您可以简单地忽略它们 - 它们不会干扰您的任何变量。

只需在脚本中声明var why;,对该元素的引用即告消失。

  

为什么不能从父对象中删除这些自动生成的变量?

首先,一般不能删除变量。只有对象属性可以 - 它只是某些全局变量是全局对象的可删除属性。

元素引用可能无法被删除,因为a)它们不是真正的属性而是代理b)它们不是全局对象本身的属性,而是它的原型或c)它们是全局范围内额外变量记录的属性。只要认为它们是神奇的,不再关心。