I've noticed that when I am trying to check for a variable within the window object, javascript will return the DOM node of an id matching the variable name. Consider the following code:
<html>
<body>
<div id='hello'>
</div>
<script>console.log(window.hello);</script>
</body>
</html>
In this example, the console will output the DOM object representation of <div id='hello'> and any of its descendants. I've also observed that overwriting window.hello doesn't affect the DOM and subsequent operations show the new assignment.
Is there a way to type check specifically for a DOM object? Alternatively, is there a way to avoid this behavior? Although not difficult, having to be conscious of page ID's when choosing namespaces seems like it could become very counter intuitive.
Some browsers will create a global variable for each id value in the document. In general, you should use:
document.getElementById("hello")
to retrieve DOM elements by id.
This is yet another reason why you should generally avoid using the global namespace any more than required as it is significantly polluted by this browser practice.
If you really want to test whether something is DOM object, you can see how that is done here: JavaScript isDOM -- How do you check if a JavaScript Object is a DOM Object?, but you should, in general, not need to do this for regular DOM programming purposes.
This is actually the HTML5 standard:
http://www.whatwg.org/specs/web-apps/current-work/#named-access-on-the-window-object
A way to be safe about this is to make all your javascript objects and functions within a "namespace":
var objs = {
someObject: document.getElementById( "someThing" ),
someFunction: function() {},
hello: {
...
}
};
//Now you can access it without interfering with the DOM "hello"
console.log( window.objs.hello );
Related
Being a C developer, I feel the urgent need to free memory as accurately as possible. But after reading some posts about memory management in JavaScript I still have some questions about that topic. As far as I understand, there is a garbage collector that will automatically free the memory when an object isn't referenced anymore and the GC can find the time. So an object that is held in a local variable is very likely to be freed when the variable goes out of scope.
Let's assume I have some custom elements (tab control, data table, inputs etc.). The classes of those custom elements have member variables where several data for the specific element is stored. Also event listeners can be attached to the elements the custom element consists of.
Let's say I have following html markup:
<my-tabbar>
<my-tab id="myTab">
<my-input></input>
<my-dataTable></my-dataTable>
</my-tab>
</my-tabbar>
Now I want to remove <my-tab>. Is it sufficient to just do
var element = document.getElementById ("myTab");
element.parentNode.removeChild (element);
element = null;
Or do I have to dereference every object of the child elements and remove their event listeners?
Setting an object to null makes it an empty object. Once the object is out of scope, the GC (when it runs) will clear it up. Setting local objects to null won't do you any good.
Example:
function whatever()
{
var something = null;
console.log( typeof( something ) );
}
whatever();
Output:
"object"
For the removal of a child node, please see this:
Does removeChild really delete the element?
Source(s):
https://www.w3schools.com/js/js_datatypes.asp
It is sufficient to remove the element. You don't even have to set the variable to null afterwards – you can trust the JS engine to free the memory when it goes out of scope.
Is there a best practice, or industry-wide standard for JavaScript naming convention for DOM element?
Take the following example:
var tarzan = document.getElementById('foobar');
What would be the most acceptable name to use so that a DOM element could be differentiated from another type of var? Should it be...
DOM_tarzan
DOMtarzan
elementTarzan
.... so on and so forth?
I want to be able to tell the difference by just looking at the variable. For example, if I see:
DOM_tarzan.remove();
... I know straightaway that "DOM_tarzan" is a DOM element, and that it is employing the standard JavaScript remove() method.
There is no mistaking or guesswork that "DOM_tarzan" is a custom object that has a user-defined "remove()" method.
Thanks.
For indicating that a JS object variable references a DOM element object, I append El (or Elem) as a suffix to the variable name, as in
var tarzanElem = document.getElementById('foobar');
Whether I include jQuery in my projects or not, i like my naming convention of variables to be $variable. Then I can easily see if the variable is a DOM element.
This question already has answers here:
Do DOM tree elements with IDs become global properties?
(5 answers)
Closed 9 years ago.
If I write html like this:
<div id="foo">Foo<div>
window.foo returns a dom-element and window.document.getElementById("foo") === window.foo returns true.
Why is that? And why does everyone use getElementById?
And on a sidenote: Why was overriding window.foo forbidden in IE7/8? And what happens if I set window.foo = "bar"?
I am not sure about the historical perspective, but HTML 5 specifies that elements are candidates to be directly exposed as properties on the window object if they have an id attribute:
The Window interface supports named properties. The supported property
names at any moment consist of the following, in tree order, ignoring
later duplicates:
[...]
the value of the id content attribute of any HTML element in the active document with a non-empty id content attribute.
The problem with this definition is that it only guarantees that if there is a <div id="foo">Foo<div> then window.foo will be defined. It does not guarantee what exactly its value will be (read the spec for the rules on how that is determined; for example, it might return a collection).
So it turns out the answer to "why use getElementById ever?" is simple: because you can depend on it to return what you expect without needing to take into account the whole document.
In general placing something inside the window object will make it global. For example:
var A = function() {
window.test = "bla";
console.log(test);
}
var B = function() {
console.log(test);
}
A();
B();
However that's not a good practice. You should not rely on any global object, because you may want to move your code to a browser that doesn't have window. Or to nodejs for example.
I find window.foo a little bit wrong, because you may have code that creates a global variable called foo. So, using getElementById ensures you that you always get DOM element.
Window.foo is working fine in your scenario, but what if the Id is something like this "foo-test" instead of "foo", you can see it will not work. it is because Javascript variables are not allowed for dashes in it....
Whereas it will work fine in case of document.getElementById
Sometimes I see in Javascript functions that, if the conversion of a variable to jQuery is used repeatedly, then it can be assigned to a local variable first:
$variable = $(variable);
Is this necessary, and how much is the cost of conversion?
No matter what, storing the object is faster than having to re-instantiate a jQuery object every time you want to use jQuery methods on it...even if it's miniscule for caching $(this) or $(anObject).
A term used to describe this method of "store now, use later" is "caching". The reason it's often called "caching" is because caching refers to storing a reference to something once and using that, without going back out to grab the same thing again, later (very non-technical, non-100% accurate description).
The major point is dealing with selectors. jQuery has to query the DOM every time, which is the expensive part. Generating the object and storing references isn't that expensive compared to DOM manipulation (and jQuery processing your selection in the first place).
If you're simply creating a jQuery object out of an object reference, it's not nearly as devastating, as the processing that takes place is the creation of the jQuery object...so it's really limited to whatever jQuery does for that. It's still good practice and still prevents some unnecessary processing. For example, this:
var element = document.getElementById("div_id");
$(element).someMethod();
// Later:
$(element).someOtherMethod();
is slightly inefficient, since a new jQuery object is created each time. It could easily be condensed to store a reference to a single jQuery object in a variable, and reference that.
The one caveat I can think of is that it isn't a live list of elements (if selecting DOM elements). For example, you may want to cache all elements with the class testing-class, like so:
var myelements = $(".testing-class");
But if another element is added to the DOM with the testing-class class, myelements will not be reflected. It will have the same, previous list. So in that case, the DOM will obviously need to be re-queried and update myelements.
To me, the best practice for caching is within a scope....not the entire page. If you are running a function, and it selects some elements, cache it at the beginning, and use that. But don't cache it globally and use it throughout your page; cache it for an execution cycle.
For example, I would do this:
function someFunc() {
var elements = $(".class-stuff");
// Use `elements` here
// code
// Use `elements` here
someOtherFunc(elements);
}
function someOtherFunc(el) {
// Use `el` here
}
someFunc();
// Some time later:
someFunc();
but I wouldn't do this:
var elements = $(".class-stuff");
function someFunc() {
// Use `elements`
}
function someOtherFunc() {
// Use `elements`
}
someFunc();
someOtherFunc();
// Some time later
someOtherFunc();
It depends on what the variable is. If the original variable is just a single DOM element then it's not particularly expensive - the DOM traversal has already been done so all you're doing is wrapping that element in the jQuery pseudo-array and attaching the prototype.
However if the original variable is a selector, then you absolutely should cache the result to avoid repeated conversions from DOM -> element list.
In any event, it's good practise not to repeat yourself, so caching $(variable) is just good code hygiene.
If the $(variable) is being called anyway this assignment has basically no cost -- this is only storing a reference to the object in memory.
Purists might point out that because the jQuery object is now stored it can't be garbage collected, and this is true. So I guess if you had lots of these it could cause a memory issue, but in itself it has no cost to speak of.
The reason it is done is because there is a cost associated with creating the object, that is the $(variable) part. That if done many times could be expensive. Store a reference to the object means only one needs to be created.
Another important point: The following statement
var $variable = $(variable);
could act different if it is done in a calling context of a closure. That is if there is a function defined in the scope of the var statement that variable will "stick around" for the function to use. This could have the same effects as described above (no gc and pointer memory) with the addition of a longer lifetime. (Because it will stay as long as the function has potential to be called.)
I read somewhere that objects were basically hash tables, and you could assign values to them willy nilly. Well, I am hoping to take advantage of this, but I want to know if it is even possible, if it is considered "correct", and, if there are any unwanted situations.
My situation:
I have a serious of objects (the kind which CANNOT be stored in the DOM!) which I want to assign to DOM objects. My plan is to:
FInd a dom object (A div, or area of some form), and then assign that to the variable myVar
I will then call: myVar.customVal = value
customVal of course is not defined in the DOM specification. Will that even work, though? Will it show up in the DOM, or stay a virtual variable? Is there any way to assign custom values to members of the DOM for access later?
You can do it:
var foo = document.getElementById('sidebar');
foo.party = 3;
console.dir(foo);
But no, it's not considered good practice. Rather, consider using HTML5's custom data attributes, or better yet, jQuery's abstraction of them.