2016-07-05 2 views
5

Это может быть не общеизвестно, но "Javascript on many (all?) modern browsers seems to create variables on the window object for DOM elements with IDs".Почему не удается удалить переменные Javascript, автоматически созданные из DOM?

Зная это, я хотел бы иметь возможность удалить эти переменные, а ниже - некоторый код, который я пробовал без успеха. Также рассмотрим мой скриншот операторов console.log, который сначала указывает why как не свойство окна (он должен находиться между «webkitUrl» и «window»), но тем не менее в двух консольных.log-операторах, которые сразу же следуют за первым , window/почему показано как 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

+3

1) Зачем вы хотите это сделать? 2) свойства 'неконфигурируемые' не могут быть удалены. – 4castle

+0

'delete' работает только с собственными свойствами, а не с унаследованными. Элементы могут располагаться дальше по цепочке прототипов. –

+0

Не может быть сделано и не должно быть проблемой. – adeneo

ответ

5

Это потому, что эти свойства не хранятся непосредственно в window. Вместо этого он ведет себя как прокси.

Например, см what Firefox does при использовании 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; 
    } 
    // ... 
} 

Вы могли бы подумать, что когда вы установите идентификатор некоторого элемента, 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(); 
} 

Такое поведение жестко закодированы, и вы не можете предотвратить его. Поэтому, если эти свойства вас раздражают, просто переопределите их, объявив свои собственные переменные.

4

Я хотел бы, чтобы иметь возможность удалить эти переменные

Там нет абсолютно никаких причин, чтобы сделать это. Эти глобальные значения are there for backwards compatibility и браузеры вряд ли удалят их. Однако они были созданы таким образом, что вы можете просто игнорировать их - они не будут мешать ни одной из ваших переменных.

Просто объявите var why; в своем скрипте, и ссылка на элемент исчезла.

Почему эти автоматически сгенерированные переменные не удаляются из их родительского объекта?

Прежде всего, переменные не могут быть удалены вообще. Только свойства объекта могут - это просто, что некоторые глобальные переменные являются удаляемыми свойствами глобального объекта.

Ссылки на элементы, вероятно, не могут быть удалены, потому что: a) они не являются реальными свойствами, а скорее проксированы; b) они не являются свойствами самого глобального объекта, а его прототипа или c) они являются свойствами запись дополнительной переменной в глобальной области. Просто считайте их волшебными и не волнуйте больше.

+1

Не знаете, почему это было приостановлено. Это хороший ответ. – Oriol

+0

Переменные (если они не указаны нигде) _should_ получить мусор. Нет? – Tuvia

+0

@Tuvia: Не когда они глобальны, как вы никогда не знаете, когда на них можно ссылаться. – Bergi