what's the difference in using closure and private class in javascript - javascript

const BUTTON = document.querySelector('.clickBtn');
const P = document.querySelector('.click');
const click = (() => {
let click = 0;
return () => ++click;
})();
BUTTON.onclick = () => {
P.textContent = click();
};
const BUTTON2 = document.querySelector('.clickBtn2');
const P2 = document.querySelector('.click2');
class Click {
#click = 0;
click = () => ++this.#click;
}
const c = new Click();
BUTTON2.onclick = () => {
P2.textContent = c.click()
};
<button class="clickBtn">CLOSURE</button>
<p class="click"></p>
<button class="clickBtn2">CLASS</button>
<p class="click2"></p>
say I have a code like above, trying to manage real-time state in vanilla JS and also wanting to hide the actual data from exposing.
I don't need multiple method
nor do I need to copy multiple instances
in case like this, would there be any difference between closure and class except class being slightly more verbose?

Related

How can I access variable outside event click

Hi everyone as title says I would like to achieve access to my variable called "Year" outside from my event.
Is that possible?
const ModifyYear = () =>
{
const button = document.querySelector(".button");
let Year = 2022;
button.addEventListener("click", () =>
{
Year = 2023;
})
console.log(Year); //2022
}
Another option is to change your program logic. Here we can use callbacks:
// Your function
const ModifyYear = cb => {
const button = document.querySelector("button");
let Year = 2022;
button.addEventListener("click", () => cb(Year+1));
}
// Call with callback function as parameter
ModifyYear(newYear => console.log(newYear));
<button>Click me</button>

How do I change a variable inside a module pattern?

I’m stuck on writing this module pattern for a tic tac toe game. When I click on a tile, it doesn’t increment gameBoard.tileCounter
const gameBoard = (() => {
const tiles = document.querySelectorAll('.game-board > div')
let tileCounter = 0;
tiles.forEach(tile => tile.addEventListener('click', () => {
tileCounter++;
}))
return {tileCounter};
})();
If I do gameBoard.tileCounter++ it works, but shouldn’t I just be able to do tileCounter++
The idea of a module pattern is to access to the properties of that module instead of having a lot variables dangling, so in your scenario you can return a function to get the counter.
Something like this might work:
const gameBoard = (() => {
const tiles = document.querySelectorAll(".game-board > div");
let tileCounter = 0;
tiles.forEach((tile) =>
tile.addEventListener("click", () => {
tileCounter++;
})
);
const getTileCount = () => tileCounter
return { getTileCount };
})();
And by doing gameBoard.getTileCount() you will be able to get the actual count

Unable to obtain element through querySelectorAll("class") , class assigned in factory function

I created 3 buttons through factory function and assigned class "btn" to them and return the object, now I want to access all the button having class "btn" , but I am getting a empty NodeList
I want to store all the button having class "btn" in tabs variable
const tabButton = function(name)
{
const button = document.createElement("button") // button creation
button.innerText = name
button.classList.add("btn")
return {button}
}
const Header = function()
{
const homeButton = tabButton("Home").button
const MenuButton = tabButton("Menu").button
const ContactButton = tabButton("Contact").button
const tabs = document.querySelectorAll(".btn")
console.log(tabs) // giving NULL value
return {tabs}
}
Your tabButton function calls create the elements, but don't put them in the document anywhere. document.querySelectorAll only looks for elements that are in the document. If you put those buttons in the document, they'd be found by document.querySelectorAll, but there isn't a function that looks through every object everywhere in memory to see if it's a button that matches. There are only functions that look in documents or specific elements.
Here's an example showing the result before and after putting those buttons in the document:
const tabButton = function(name) {
const button = document.createElement("button");
button.innerText = name;
button.classList.add("btn");
return {button};
};
const Header = function() {
const homeButton = tabButton("Home").button;
const menuButton = tabButton("Menu").button;
const contactButton = tabButton("Contact").button;
console.log(document.querySelectorAll(".btn").length); // 0
document.body.appendChild(homeButton);
console.log(document.querySelectorAll(".btn").length); // 1
document.body.appendChild(menuButton);
console.log(document.querySelectorAll(".btn").length); // 2
document.body.appendChild(contactButton);
console.log(document.querySelectorAll(".btn").length); // 3
const tabs = document.querySelectorAll(".btn");
return {tabs};
};
Header();

React dynamically add html element with event handler

Is it possible to append buttons with event handler in react ?
// This is working fine but its pure javascript onclick , how can I make this element with react js onClick ?
This is reference code , my scenario is appending html code dynamically
const Button = () => {
const dynamicElement = () => {
let li = document.createElement('li');
li.className = 'dynamic-link'; // Class name
li.innerHTML = "I am New"; // Text inside
document.getElementById('links').appendChild(li);
li.onclick = function(){ alert(0) }
}
useEffect(() => {
dynamicElement();
}, [])
}
You can just convert your function to a functional component like this.
const DynamicElement = () => {
return (
<li onClick={()=>alert(0)} className="dynamic-link">I am New</li>
)
}
const Button = () => {
const [visible, setVisible] = useState(false);
useEffect(()=>setVisible(true), [])
// if visible is true return <DynamicElement/>, either way return null
return visible ? <DynamicElement/> : null
}
BTW useState is hooks implementation of a state

Override a function already attached to an event

I want to override a function already attached to an event. Like that :
let orFn = () => {
console.log('old');
};
buttonEl.addEventListener('click', orFn);
orFn = () => {
console.log('new');
};
However, when I click on the button, the old function is still called.
I have seen this stackoverflow. I can't use a function wrapper in my case. And I want to understand why this is not working.
My code is available for testing here: jsfiddle.
One way is to remove first listener, then add another one
let orFn = () => {
console.log('old');
};
let orFnNew = () => {
console.log('new');
};
var buttonEl = document.querySelector('button')
buttonEl.addEventListener('click', orFn);
// remove old listener
buttonEl.removeEventListener('click', orFn);
// add another one
buttonEl.addEventListener('click', orFnNew);
<button>button</button>
Another way is to have one listener, that may call different functions inside. Example:
// button
const buttonEl = document.querySelector('button')
const orFn = () => {
console.log('old');
};
const orFnNew = () => {
console.log('new');
};
// function that will be called
let functionToCall = orFn;
buttonEl.addEventListener('click', (event) => { // single listener
functionToCall.call(event); // call a function with event
functionToCall = functionToCall === orFn ? orFnNew : orFn; // change function to be called
});
<button>button</button>
One way of using bind().
const btn = document.getElementById('btn');
let orFn = () => {
alert('old');
};
orFn = () => {
alert('new');
};
orFn.bind(orFn)
btn.addEventListener('click', orFn);
This will bind with new function and show new in alert Popup.

Categories

Resources