I am trying to understand memory leak and I have read blogs as following:
How to handle 4 common memory leaks
Avoiding Memory Leaks in JavaScript
Unfortunately, I still feel confused on this issue.
So, I try to make a test like this:
Firstly, I create a pure HTML containing a huge table within a div#box:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<div id="box">
<table>
<tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5</td></tr>
... hiden 2400 lines of same content row intended for simplicity ...
<tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5</td></tr>
</table>
</div>
</body>
</html>
Then open the devTool and use Console and Memory to make actions and memory recoding:
// 1. Initial "heap snapshot" get 1.9MB
// 2. Running following code on "Console" and "heap snapshot" get 2.2MB
var box = document.getElementById("box");
var tab = document.querySelector("table");
box.removeChild(tab);
tab = null;
// 3. Running following code on "Console" and "heap snapshot" get 2.2MB
box.parentElement.removeChild(box);
box = null;
My confusing is why I almost empty this html DOM tree but the memory consumption is increased.
Any explanation about on JavaScript memory leak will be appreciated! Thanks in advance!
Related
SOLVED: So the problem was that the program broke at when I declared userInput but that was already declared in the js file that I initialized right before this app.js file. Once I changed the name it seems to be better now, thanks all! :D
So i've started a JS tutorial and all the code is doing weird things and not executing in the proper order no matter how many times I close and reopen the program.
I am working on a calculator program from the tutorial so i've copied the code how it appears.
Here is the file structure:
Here is my index.html (notice the script tags at the end of the body)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>Basics</title>
<link
href="https://fonts.googleapis.com/css?family=Roboto:400,700&display=swap"
rel="stylesheet"
/>
<link rel="stylesheet" href="assets/styles/app.css" />
</head>
<body>
<header>
<h1>The Unconventional Calculators</h1>
</header>
<section id="calculator">
<input type="number" id="input-number" />
<div id="calc-actions">
<button type="button" id="btn-add">+</button>
<button type="button" id="btn-subtract">-</button>
<button type="button" id="btn-multiply">*</button>
<button type="button" id="btn-divide">/</button>
</div>
</section>
<section id="results">
<h2 id="current-calculation">0</h2>
<h2>Result: <span id="current-result">0</span></h2>
</section>
<script src="assets/scripts/vendor.js"></script>
<script src="assets/scripts/app.js"></script>
</body>
</html>
I put the script tags at the end of the body so the site content is generated first but it still runs the script first sometimes, and only when I refresh enough times does it stop. Weird...
app.js
let currentResult = 10;
currentResult = currentResult + 10 * 3;
let calculationDescription = `${currentResult} (0 + 10)`
outputResult(currentResult, calculationDescription)
alert("hello")
And then when I press Ok on the alert
Only then does the calculation get done. Which is strange because the calculation is written to be executed BEFORE the alert (The calculation did appear a few times while the alert was active, but only 15 seconds later, it doesn't even do that anymore)
When I add..
const userInput = 123;
let result;
After the alert in app.js, the alert stops running entirely!
This makes no sense to me. I wanted to have some js code after the alert so I can put in another alert but this file is making it seem like the alert MUST be the last thing in a js file OR there can only be approx 5 lines in a js file.
Also, the css in the project wasn't working until I moved the entire project from my downloads folder to my desktop (and removed the 5 parent folder hierarchy over it) and there the css did work...
Any idea what can be causing this mess, or is my computer just cursed?
Assumptions:
I've saved the code so it is fully updated
I am using VScode
Running from my OneDrive folder on Windows 10
You essentially asked three questions here:
Why do I see result of my calculation only after closing the alert?
Why does adding const userInput = 123; let result; after the alert prevent the alert from showing up at all?
Why is my CSS not working in some circumstances?
Let me answer all:
Answer to Question 1: Order of execution
The code does execute in order. You can see that if you use the devtools debugger to step through it line by line. What's tripping you up is when the browser redraws page content, as this happens at the end of a tick, when there is no more code to be run in that tick. Rerendering the page instantly whenever something on it gets changed would be very slow (and could induce flicker, depending on what it is that you are updating).
So what happens is this:
Your calculation result is set as content of your element. (But you don't see it yet since the page hasn't been redrawn yet.)
Your alert shows up.
You close the alert.
The call to the alert function returns and the code continues.
No more code is there to run (at least synchronously), and the page is redrawn. (Now you see the changed content.)
In the rare cases where the calculation did show up 15 seconds later, it was probably that something else, something external (such as maybe resizing the window) triggered a redraw despite the alert still being open.
alert isn't the best way to get output anyway, for several reasons: it also obscures a lot of information about more complex data types because it coerces everything to a string, and you cannot easily trace the source of the alert or log the exact time it was shown - all of which are things that console.log would do better.
Answer to Question 2: Why adding code can break everything
Most likely you were introducing a syntax error at that point. For example you may have already declared userInput or result previously, and adding that code made the whole file invalid with a SyntaxError: Identifier 'result' has already been declared or the like, so it wouldn't execute at all.
That's because when a script file (or a <script> tag content) is loaded, it's first parsed (at which point you can encounter "compile-time errors" such as a SyntaxError) and only then it's executed (and then you can encounter "runtime errors" such as a ReferenceError). If you add a single bad character at the very end of your file that's causing a SyntaxError during parsing, the whole file will no longer run.
You would see this error and where it originates from if you'd look into the console tab of your devtools.
In general, I can only recommend learning how to use devtools rather sooner than later: https://www.youtube.com/watch?v=Y3u2groOG-A
Answer to Question 3: Missing styles
It's hard to tell with the information given. Again, a good start would be to check in your devtools for errors in regards to loading the CSS file (in console and network tabs). Also, in case you are using a file:// URI, I'd recommend switching to a local HTTP server instead. Many things behave differently with file:// URIs compared to http:///https://.
Totally new to JavaScript. As in, today.
From an .html file on my MacBook desktop, I want to open TWO webpages. The first is the file itself, say from the command line, as follows:
open ~/Desktop/first.html
The second webpage is one that I call from the first.html file:
<!DOCTYPE html>
<head>
<meta charset="utf-8" />
<title>JavaScript stuff</title>
</head>
<body>
<script>
w = window.open('https://fireship.io/courses/javascript/beginner-js-where-to-run/');
const elements = w.document.querySelectorAll('*');
const count = elements.length;
alert(count)
elements.forEach((elem) => {
console.log(elem)
});
</script>
</body>
</html>
WHAT I WANT TO BE HAPPENING is that w.document.querySelectorAll('*') is getting all elements in the second webpage, meaning https://fireship.io/courses/javascript/beginner-js-where-to-run/. WHAT'S ACTUALLY HAPPENING, though, is that the elements from first.html are returning. This is confirmed by inspecting the console output of first.html.
So, my general question is --- How do I loop through the elements of one webpage from scripting that resides in another?
Any help or direction is much appreciated!
Justin
I have homework for my programming class which requires that I work with JS classes. On top of that, I have to work with HTML and the classes have to be defined on a separate .js file. I've done all the work, and it runs ok if the classes are defined on the same .js file, but it stops working as soon as I paste the code on a different file. I've tried importing the classes on the primary file, but I could make it work (I've tried different import codes because I've found different answers to this question on Google but no one worked, that's why I'm asking here). I believe it's probably because I'm doing something wrong at importing, but I just can't find the error.
Although your code works, keeping js files at the top of the HTML will delay the load time of the page. In a simple scenario like a homework, there's no need to worry, but in large projects it becomes crucial.
And by reading your code, it just starts when all page has already loaded, so no need to put it in the head.
Have you tried doing this:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script src="first.js"></script>
<script src="second.js"></script>
<p>Hello World!</p>
</body>
</html>
First, I'll share some code. This is my HTML head:
<head>
<meta charset="utf-8">
<title>Obligatorio1</title>
<link rel="stylesheet" href="css/estilos.css">
<script src="js/funciones.js"></script>
<script src="js/clases.js"></script>
</head>
This is my relevant code on the first JS:
window.addEventListener('load',inicio)
function inicio(){
document.getElementById("botonAgregarPersonas").addEventListener("click",registroPersonas);
}
let personas=[];
function registroPersonas(){
let nombre=document.getElementById("nombrePersonas").value.trim();
let seccion=document.getElementById("seccionPersonas").value;
let mail=document.getElementById("emailPersonas").value.trim();
let esta=false;
for (i=0;i<personas.length&&!esta;i++){
if (nombre==personas[i].nombre) {
esta=true;
}
}
if (esta){
alert("Nombre ya ingresado");
}else {
let Per = new Persona (nombre, seccion, mail);
personas.push(Per);
let texto=Per.nombre+" - Sección: "+Per.seccion+" - "+Per.mail;
agregarElementoEnLista(texto);
agregarEnComboCompras(Per.nombre);
agregarCheckboxes(Per.nombre);
}
}
function agregarElementoEnLista (texto){
let nodoLi=document.createElement("LI");
let nodoTexto=document.createTextNode(texto);
nodoLi.appendChild(nodoTexto);
document.getElementById("lista").appendChild(nodoLi);
And this is the code of my second JS file (the one with the class):
class Persona{
constructor(nombre, seccion, mail){
this.nombre=nombre;
this.seccion=seccion;
this.mail=mail;
}
}
I'll start saying that, while I've found out the issue, I don't understand why does it happen.
Ok, as you can see on the last piece of code, the parameters have the same name as the class attributes. If I would try copying the code on the first JS file, it would work without any issue, but as soon as I work with that code on a separate JS file it would stop working. After touching every part of the code, I ended up changing the parameters name so it would be different than the class attributes, it looks like this now:
class Persona{
constructor(_nombre, _seccion, _mail){
this.nombre=_nombre;
this.seccion=_seccion;
this.mail=_mail;
}
}
And that code right there works totally fine, without changing anything on the rest of the files (neither the first JS file nor the HTML one).
If anyone understands more than me on why does this happens, feel free to edit this answer.
Thanks everyone for the help!
I realize this is a horribly newbie question, but Ive been trying to fix it for days trying different methods so I just wanted to ask what would you do.
I am attempting to create a web program to use at work, and I have this setup:
Windows 7
IE 7 - Cannot Upgrade.
The "website" is not a webhost, basicly I have a folder on my desktop with html/css/js files and I use IE to run the scripts, no host.
I want to keep a set of vars, mostly strings, in an external JS file and pull the JS into different HTML pages. I want it to write on load of the document.. not on ready. It does not have to be user dynamtic.
Also, When I make the js file, does it have to have a header.. like HTML has doctypes?
I really appreciate your help as I am trying to learn and will cont on my own from here. My setup is much different than most, and im not sure which part was causing my problem so I finally broke down and posted.
When you write your JavaScript file it doesn't have to have any header or doctype. For example you can have a variables.js file that looks just like this:
var x = "abc";
var y = "def";
and have many HTML files that include variables.js like this:
<!doctype html>
<html lang=en>
<head>
<meta charset=utf-8>
<title>title</title>
</head>
<body>
<!-- page content -->
<script src="variables.js"></script>
<script>
alert(x);
</script>
</body>
</html>
and your variables should be available there. Any script that is included after the reference to your variables.js should have access to everything that was included before without the need to listen to any events.
If you need to listen to the events then I suggest to use jQuery or some other JavaScript framework. An example for jQuery would be:
$(window).load(function() {
alert(x);
});
A more advanced example of changing the DOM elements:
<!doctype html>
<html lang=en>
<head>
<meta charset=utf-8>
<title>title</title>
</head>
<body>
<p>Select variable:</p>
<p>
Show x
Show y
</p>
<p>Value:</p>
<p id="value"></p>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script src="variables.js"></script>
<script>
$('#show-x').click(function (e) {
e.preventDefault();
$('#value').html(x);
});
$('#show-y').click(function (e) {
e.preventDefault();
$('#value').html(y);
});
</script>
</body>
</html>
If it's not a global variable, you can't display/print/access or whatever you call it because it has a local scope, defined in a function.
You can probably only use a debugger simply to debug it
I have a large web page (internal, in development) that is taking too long to load. Specifically, loading the 2.3MB HTML page shows the styled content in ~3s, and then the browser locks up for over 20s before becoming interactive.
Using Chrome's Timeline I can see that this is all due to script being kicked off as part of the load event:
However, when I profile the page load I see this (click for full size):
32.01 seconds are spent in some anonymous function with no associated source code. As part of that, 18.87 seconds are spent in the function "get length" (which also has no associated source code).
What is get length? Is there no better information available from the profiler about where time is being spent?
This is call to a length attribute of the form (or any other DOM element with the native length attribute.
This is an example code I used
<!DOCTYPE html>
<html>
<head>
<title></title>
<script type="text/javascript" src="js/lib/jquery.js"></script>
<script type="text/javascript">
var doStop = false;
$(function(){
//recursively append dot-button to the form and show its length
function a(counter) {
var $w = $('#wrapper').append($('<button>.</button>'));
$('#txt')[0].innerHTML = 'Form length: '+$w[0].length;
if (!doStop)
setTimeout(function(){ a(counter+1)}, 3);
}
$('#stopper').click(function(){ doStop = true; });
a(0); //let's go now
});
</script>
</head>
<body>
<button id="stopper">stop it</button>
<div id="txt"> </div>
<form id="wrapper"></form>
</body>
</html>
I get the following in the Chrome profiler:
| 0.08% | 0.08% | get length |
I do have an arrow beneath it to drill down through function a() though.