知道这一点我希望能够删除这些变量,以下是我尝试过的一些代码但没有成功。还要考虑我的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>
答案 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)它们是全局范围内额外变量记录的属性。只要认为它们是神奇的,不再关心。