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)
那是因为这些属性不是直接存储的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)
此行为是硬编码的,您无法阻止它.因此,如果这些属性惹恼了您,只需通过声明自己的变量来覆盖它们.