0

When writing some Javascript, I usually define upfront all the elements I need, e.g.

var $body, $header, $footer, $anInput;

$(document).ready(function () {
  $body = $('body');
  $header = $('div#header');
  $footer = $('div#footer');
  $anInput = $('form#myForm input');
};

Now, If I do something like

$body.html($body.html());

(I know, does not make sense, but it could be for instance obtained via an AJAX call).

Am I still entitled in using $header, $footer, $anInput or should I get the reference once again?

Actually, my Javascript code still works, so I would answer yes, but I suspect that I'm missing something.

1
  • i had done a project that i faced with the same problem and i found out that it change and i had to reference them again. Commented Mar 12, 2017 at 22:10

3 Answers 3

1

Your jQuery reference will be wiped. So, if you decide to do $body.html($body.html()), your selectors will all break.

$(document).ready(function () {
  $body = $('body');
  $header = $('div#header');
  $footer = $('div#footer');
  
  $footer.html("test 1");
  
  $anInput = $('form#myForm input');
  
  $body.html($body.html());
  
  $footer.html("attempted to change value");
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<body>
	<div id="header"></div>
	<div id="footer"></div>
</body>

Notice how footer is still test 1.

You just need to re-initialize the selectors.

$header = $("div#header");
Sign up to request clarification or add additional context in comments.

Comments

1

That because when using jQuery.html or Node.innerHTML the entire content of the element is removed and replaced by new content. And since elements (nodes) are objects, and objects in javascript are passed by reference not by value, the old references will point to object that have been removed, thus the references will be useless and error-prone if used.

You can store selectors instead of jQuery objects and use $(...) like this:

header = 'div#header';
footer = 'div#footer';
anInput = 'form#myForm input';

$(header)....;
$(anInput)....;
// ...

Or update the objects every time you change the HTML which is better because then you'll call $(...) less times which is a bonus in performance.

3 Comments

Mhhh, I suspected something like this. Well, then I would say that caching selectors in variables like I do is not a good idea when I have no guarantee that the html will not be replaced somehow in the future by such a DOM manipulation. Do you agree?
But what is the benefit of storing selectors? Once I call $(selector) the DOM will be traversed, again.
@mat_boy Agree! You'll have to update every time the HTML change (best approach) or instead of storing objects store the selectors and call $(...) on the selectors (not better than the first one but still a best approach).
0

You can check this yourself: the references still point to objects which can manipulate them however you want, but the objects they refer to are no longer in the DOM, so they don't affect anything you can see in the browser. And any event listeners that were attached to any elements in the body were also removed, so you'd have to attach new ones. Your options:

  • Get new references to the implicitly inserted DOM elements (or in your case jQuery wrappers around them) each time. This becomes really difficult to maintain as complexity grows and components change.
  • Keep component updates more atomic, so that you never replace whole DOM elements, only modify text or attribute values. Good rule of thumb.
  • Or always render the whole page again (attaching listeners etc.) from an authoritative state. Which might mean not using frameworkless jQuery anymore.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.