I saw a strange behavior.
I created a Input.
<input id='inputid' value='value'/>
and tried to access it directly from id. Instead of throwing an exception console was showing above input element.
console.log(inputid);
After that I tried to compare it with getElementById
console.log( inputid == document.getElementById('inputid'));
console was showing true.
You can see this behavior on jsfiddle.
Is it a strange behavior or am I missing something?
I tested it in Chrome 23.0.1271.10 dev-m and firefox 15.0.1.
Back in the days of 4.0 browsers, Microsoft decided that it would be convenient to create, for every element with an id, a global variable with the same name as the id containing a reference to that element.
Support for this has appeared in some other browsers (in some rendering modes). This support is not universal so the feature should be avoided.
To just expand a little on this situation based on a curiosity:
<html><head>
<script type="text/javascript">
var overWrite = "world";
window.onload = function(){ alert(overWrite); };
</script></head><body>
<input id="overWrite" value="hello" />
</body></html>
Will alert "world". However, with //var overWrite = "world"; (as in with that line commented out), it will alert the [html element]. Note that this is after the page loads so it is persistent and not some sort of temporary assignment.
Strongly agree that it should not be used due to inconsistency and readability issues.
EDIT
Still was curious about this issue and did some more testing. I was curious if access was faster with document.getElementById or by variable reference. Made this test:
html
<div id="contentZone"></div>
js
var startTime = Date.now();
for( var i = 0; i < 1000; i++){
for( var n = 0; n < 2000; n++){
var ni = document.getElementById("contentZone");
}
}
var endTime = Date.now();
console.log( endTime - startTime );
var aTime = Date.now();
for( var i = 0; i < 1000; i++){
for( var n = 0; n < 2000; n++){
var ni = contentZone;
}
}
var bTime = Date.now();
console.log( bTime - aTime );
console
431
814
Tested on this machine only, but it would seem that using document.getElementById is still faster making this variable access even less desirable.
Related
I am testing a snippet of JavaScript's speed using the console.time(); method in Chrome and Chromium-based Edge. When I'm running the snippet in the browser, it takes at least 2 seconds, but the displayed result of time is around milliseconds, What is happening here?
var list = [...Array(50000000).keys()];
console.time("time");
var x = 0;
for (let i = 0, n= list.length; i<n ;i++) {
x++;
}
console.timeEnd("time");
I've tested this with performance.now() and I get the same result as time, which is really confusing however it works perfectly fine in Firefox.
Is this a Chrome/Edge bug? if it is, How can one submit an issue for chrome?
Update
Thanks to #vlaz and #Jax-p I found out that I've missed the array generation time:
console.time("time");
var list = [...Array(50000000).keys()];
var x = 0;
for (let i = 0, n= list.length; i<n ;i++) {
x++;
}
console.timeEnd("time");
Creating and spearding array with [...Array(50000000).keys()]; takes over 1.5s in my Chrome but you have timer start after that (You had. Before you change the question.). I am getting same (a little bit higher) results in Firefox. Can it be it?
Suppose there is also a delay before the browser even gets to execute JavaScript.
console.time("time");
var list = [...Array(50000000).keys()];
console.timeEnd("time");
console.time("time2");
var x = 0;
for (let i = 0, n= list.length; i<n ;i++) {
x++;
}
console.timeEnd("time2");
I trying to make a small text based rpg game, but I came across array in js and then I came to problems, I failing to increase the index number by using i instead of 0 like myArray[i]
I made a jsfiddle so you guys can see what I mean.
jsfiddle
When you press the button til you get a warming, it should increase the i to 2, but it don't, but still comes with warming and increasing the attack variable.
This is your attackUp function:
function attackUp(){
var i = 0;
var attackCost = xpforlevel[i];
if (attackCost < attackxp) {
alert("WARMING!");
attack++;
document.getElementById('attack').innerHTML = attack;
i++;
document.getElementById('i').innerHTML = i;
}
}
Notice that your var i = 0 statement doesn't really make sense (because everytime attackUp is called, i will be reset to = 0 at the beginning). To fix that, erase this var i = 0 statement from your function and put in the beginning of your JS code:
var i = 0;
var attackxp = 0;
var attack = 1;
Further, your function will only update i if attackCost < attackxp, otherwise it will change nothing. You need to put the i++; statement outside your if-block, like this:
function attackUp(){
//erase this line: var i = 0;
var attackCost = xpforlevel[i];
i++; //added this line
if (attackCost < attackxp) {
alert("WARMING!");
attack++;
document.getElementById('attack').innerHTML = attack;
//erase this line: i++;
document.getElementById('i').innerHTML = i;
}
}
As your i is a local variable, it is initiated as 0 every time you call attackUp(). You should put it besides attackxp and attack.
For more information about the scope of variable in JavaScript, see w3schools or this question.
I am new to JavaScript. I don't know why my code does not work. I am creating functions for returning card stacks quantity. The user will input the card stack quantity. Then the card stacks will be remixed with the following rules. But the result does not appear. Can you please help debugging this code..
<!DOCTYPE html>
<html>
<body>
<h1>JavaScript Functions</h1>
<p id="demo"></p>
<script>
var reposition = [];
function Reverse(userinput){
var array = new Array(userinput);
var trueform = new Array(userinput);
for(var i=0; i<userinput; i++){
array[i] = i + 1;
trueform[i] = i + 1;
}
while(! (isEqual(trueform,reposition))){
for(var ii=0; ii<userinput; ii++){
reposition[userinput-ii-1] = array[ii];
if((ii+1) != userinput){
swap((ii+1));
}
}
for(var iii=0; iii<reposition.length; iii++){
array[iii] = reposition[iii];
}
count +=1;
}
return count;
}
function swap(n){
var temp = array[n];
for(var iiii=n; iiii<array.length-1; iiii++){
array[iiii] = array[iiii+1];
}
array[array.length-1]= temp;
}
function isEqual(t, r){
for(var iiiii=0; iiiii<t.length; iiiii++){
if(t[iiiii] != r[iiiii]){
return false;
}
}
return true;
}
document.getElementById("demo").innerHTML = Reverse(4);
</script>
</body>
</html>
The first thing I notice is the variable array is not defined. This is because you are trying to use it in separate functions.
this.array instead of var array
The second thing I notice is that in your while loop you are doing count += 1 which is also not defined anywhere in your code.
I recommend starting with a debugger of some sort so you can even find out what errors you are getting. If you're using Chrome, you can open their DevTools with F12. IE and Firefox both also have their own dev tools and I think they both also use F12 as their hotkey.
Here's a link to the instructions for the Chrome DevTools
Otherwise #DavidR2016 is right about some of your variables being undeclared at runtime in the swap and Reverse functions. It's a little hard to read your code as it is pasted in the question, but when I copied to NotePad++ I was able to format and read it a little better. You also do not need to increment the number of i's in your for loops. You can use just one i because they are scoped to the specific loop, and that will also help with readability.
I have a problem regarding 'offsetHeight' property does not get updated after updating font size. Bellow is the code.
function shrink_toolbar_text()
{
var toolbar = document.getElementById("toolbar");
var icons = document.getElementsByClassName("icon-alone");
var icon_size = 64;
var icon_height = icons[0].offsetHeight ;
while( icon_height > toolbar.offsetHeight)
{
// textSpan.style.fontSize = parseInt(textSpan.style.fontSize) - 1;
icon_size = icon_size -1;
for ( i=0; i< icons.length ;i++){
icons[i].style.fontSize = icon_size ;
}
icon_height = icons[0].offsetHeight ;
console.log( icon_height);
console.log( icon_size);
// console.log( parseInt(icon_size));
}
console.log("shrink_toolbar_text() ");
}
any workaround on this situation ?
I've tried following things so far.
1. Try to redraw each and every icons using show and hide.
2. Tried 'getComputedStyle()' but it don't return a value called 'offsetHeight' at all.
Any idea why code is not working?
The code should be corrected to this.
var icon_size = 64px;
and
icons[i].style.fontSize = icon_size+"px" ;
In some browsers, this code won't work without postfix 'px'. Neither it emit a error message on console. So careful coding on this.
How can I replace a text or number in a span element with javascript/jquery?
this is what i have tried but the console says "Cannot call method 'replace' of undefined" dont understand whats the problem, can someone point me in the right direction?
function changeNumber()
{
var element = document.getElementsByClassName("grade").innerHTML;
var x = element.replace('1','*');
document.getElementsByClassName("grade").innerHTML=x;
}
If it matters the span element i created dynamically in javascript...
document.getElementsByClassName("grade") returns a NodeList, it is not like getElementbyId, you need to loop it.
If you just have one
function changeNumber()
{
var element= document.getElementsByClassName("grade")[0];
var text = element.innerHTML;
var x = text.replace('1','*');
element.innerHTML=x;
}
If you have a set
function changeNumber()
{
var elements= document.getElementsByClassName("grade");
for (var i=0; i<elements.length; i++) {
var element = elements[i];
var text = element.innerHTML;
var x = text.replace('1','*');
element.innerHTML=x;
}
}
If you already have jQuery included in your page, and are comfortable with it's usage, try the following code:
function changeNumber()
{
$(".grade").each(function(){
var self = this
self.text(self.text().replace('1','*'))
});
}
Working demo: http://jsfiddle.net/pratik136/uUHv8/
While the posted answers are correct, and despite the fact that you've accepted an answer, I was intrigued by the possibility of creating a replace() function to work with a nodeList (or, strictly-speaking, an Object), so:
Object.prototype.replace = function (n, r) {
var textMethod = this[0] && this[0].textContent !== undefined;
for (var i = 0, len = this.length; i < len; i++) {
if (textMethod) {
this[i].textContent = this[i].textContent.replace(n, r);
} else {
this[i].innerText = this[i].innerText.replace(n, r);
}
}
return this;
};
document.getElementsByTagName('p').replace(/1/, '*');
JS Fiddle demo.
I can confirm this works in Chrome 25, Firefox 19 (also 14 and 18, hadn't updated this computer in a while) under Win XP. I can't test in IE, since it, and JS Fiddle, seem to be having issues.
It may, also, not be a good idea; but it seemed useful (and relatively interesting) at the point at which I put it together. Hopefully it may be of some use.