Reputation: 67
I'am kind of new to javascript and today I was working on a function that basically toggles a value and displays it as alert but I stumbled across a weird behavior of JavaScript relating to true/false and 0/1.
The following code , when user clicks on toggle anchor link, it doesn't seem to toggle the value and the alert always gives "true" (which i thought should happen):
document.body.innerHTML = '<a href="#" id="toggle"> toggle </a>'+ document.body.innerHTML;
function f() {
this.status = true;
var btn = document.getElementById("toggle")
btn.addEventListener("click", () => {
if (this.status == true) {
alert(this.status)
this.status = false;
} else {
alert(this.status)
this.status = true;
}
}, false)
}
f()
But if I use 0 and 1 instead of true/false the code works for some reason.
document.body.innerHTML = '<a href="#" id="toggle"> toggle </a>' +document.body.innerHTML;
function f() {
this.status = 1;
var btn = document.getElementById("toggle")
btn.addEventListener("click",()=>{
if(this.status==1){
alert(this.status)
this.status = 0;
}else{
alert(this.status)
this.status = 1;
}
},false)
}
f()
I have no idea what's going on here, Is this because of this
pointer i am using in the function or something?.
Upvotes: 2
Views: 221
Reputation: 1874
The problem is that your function f
is called without new
so the this
refers to the window
object, which already has astatus
property with its own meaning.
You can see this if you print its type:
function f() {
this.status = true;
console.log(typeof this.status);
}
f()
Note how the result is string
instead of the expected boolean
.
But if you name it differently:
function f() {
this.myprop = true;
console.log(typeof this.myprop);
}
f()
It yields the correct type.
So to make it work you need only to change its name. But the if
else
logic you have to invert the boolean
can be turned into a !
(not), which simplifies the code a lot:
document.body.innerHTML = '<a href="#" id="toggle"> toggle </a>' + document.body.innerHTML;
function f() {
this.myStatus = true;
var btn = document.getElementById("toggle");
btn.addEventListener("click", () => {
this.myStatus = !this.myStatus; //here the value is inverted only with the ! (not)
console.log(this.myStatus);
}, false);
}
f();
But using the window
object is discouraged, for reasons much like the one you were experiencing, and the myStatus
property is still being stored there.
You can improve the solution a bit more:
document.body.innerHTML = '<a href="#" id="toggle"> toggle </a>' + document.body.innerHTML;
function f() {
let myStatus = true;
var btn = document.getElementById("toggle");
btn.addEventListener("click", () => {
myStatus = !myStatus; //here the value is inverted only with the ! (not)
console.log(myStatus);
}, false);
}
f();
Also, don't forget to finish the statements with the semicolons, i noticed that you had almost none of them.
Upvotes: 4
Reputation: 667
Other people have posted some good responses, but here's my two cents.
You can initialize a local variable in your function that will initialize a value and then alternate on that value when the button is clicked. Your use of this
notation does not seem to be necessary here.
document.body.innerHTML = '<a href="#" id="toggle"> toggle </a>'+ document.body.innerHTML;
function f() {
var status = true;
var btn = document.getElementById("toggle")
btn.addEventListener("click", () => {
if (status === true) {
alert(status)
status = false;
} else {
alert(status)
status = true;
}
}, false);
}
f();
When using this, always know what you are referring to. As Isac pointed out, your this
referred to the document window, which seems to have been an issue.
Codepen:
https://codepen.io/foozie3moons/pen/gGRBxZ?editors=0010
Upvotes: 0
Reputation: 5626
Since you're new to JavaScript you probably haven't heard, but you should know when to use === instead of == (hint: always).
In a nutshell, because JavaScript is weakly/un-typed it can be difficult to know if you're actually comparing two of the same thing (numbers) or two different things (number and object):
new Number(10) == 10 // true
new Number(10) === 10 // false
Because:
typeof Number(10) // returns number
typeof 10 // returns number
typeof new Number(10) // returns object
^ Above example from https://coderwall.com/p/bqurhg/why-always-use-in-javascript
Upvotes: 0
Reputation: 503
document.body.innerHTML = '<a href="#" id="toggle"> toggle </a>'+ document.body.innerHTML;
function f() {
let status = true;
let btn = document.getElementById("toggle");
btn.addEventListener("click", () => {
if (status === true) {
alert(status);
status = false;
} else {
alert(status);
status = true;
}
}, false)
}
f();
Upvotes: -1