Why Use Function Parameters Vs. Global Variables? - javascript

Yes, I know that this is probably a very stupid question, but this has been bugging me for a while.
Ok, so I have been learning JavaScript for a while now and have understood everything perfectly. . .except for function "parameters" (I believe they are called).
I was taught that they work like so:
function test(number) {
document.write(number);
};
test(1);
test(12);
This makes perfect sense to me. However, recently, I've come across some that were a little different.
var counterDays = document.getElementById('days');
var counterHours = document.getElementById('hours');
var counterMinutes = document.getElementById('minutes');
var counterSeconds = document.getElementById('seconds');
var date = new Date('December 28, 2016 00:00:00');
function updateTimer(date) {
var time = date - new Date();
return {
'days': Math.floor(time / (1000 * 60 * 60 * 24)),
'hours': Math.floor((time/(1000 * 60 * 60)) % 24),
'minutes': Math.floor((time / 1000 / 60) % 60),
'seconds': Math.floor((time / 1000) % 60),
'total': time
};
};
function startTimer(counterDays, counterHours, counterMinutes, counterSeconds, date) {
var timerInterval = setInterval(function() {
var timer = updateTimer(date);
//Changes the text of the 'counter'
counterDays.innerHTML = timer.days;
counterHours.innerHTML = timer.hours;
counterMinutes.innerHTML = timer.minutes;
counterSeconds.innerHTML = timer.seconds;
window.onload = function() {
startTimer(counterDays, counterHours, counterMinutes, counterSeconds, date);
};
<span id="days"> </span>
<span id="hours"> </span>
<span id="minutes"> </span>
<span id="seconds"> </span>
What I seriously do not understand is why the updateTimer always needs date within the parentheses, when the variable date is an already existing variable within the global scope. Same with startTimer. I don't understand why I need to pass that in. Why not just access the variable within the function, as they do have a global scope, and be done with it. Instead I need to pass in the variable as a parameter, for the function to work.
I've tried and tried, but the only way to make the function work is by passing in the variables. Why is that???
As I am still learning, I've searched the internet for more information on functions and their parameters, but all show me something similar to my first example. I know this is all probably just going over my head, but for the life of me, I just do not understand.
Note: I am still learning, so sorry if this whole question is plain stupid.
Also, the the code for the JS that I am having a problem with won't actually run. This is due to me not wanting to put in all of my code, but rather just the code I am having trouble with.

Instead I need to pass in the variable as a parameter, for the
function to work.
You dont need to define your functions with parameters. You can invoke them leveraging higher scope variables
https://developer.mozilla.org/en-US/docs/Glossary/Scope
This:
var x = 'baz';
function foo(x) {
return x;
}
foo(x);
will do the same thing as:
var x = 'baz';
function foo() {
return x;
}
foo();
Writing functions that take parameters as input helps keep your code modular and side effect free among many other benefits...
1.) The second example will always throw an error if x is not accessible at a higher scope
2.) If another function mutated the value of x it would affect the output of the second example and would lead to unexpected and potentially hard to debug behavior in your application. Whereas I can always be sure of the output of the first example
3.) It is much easier to read through and maintain code that is written in the style of the first example

As I see see your code
var timer = updateTimer(date);
Kindly remove date parameter here as well as in the called function. Now the date variable will work as in global scope.
So it will be
function updateTimer()
{
//date variable will be present here as global variable
}
var timer = updateTimer();

Related

I declared my variable with let but it is still not in global scope

I am trying to make a component appear on condition of 'uneligible=(age<18)' so I tried to declare uneligible out of his function's scope and declaring it with let because I know the value will change later
let uneligible;
const handleSaveGeneral = async (e) => {
var dateOfBirth = "2007-01-01";
var split_dob = dateOfBirth.split("-");
var month = split_dob[1];
var day = split_dob[2];
var year = split_dob[0];
var dob_asdate = new Date(year, month, day);
var today = new Date();
var mili_dif = Math.abs(today.getTime() - dob_asdate.getTime());
var age = mili_dif / (1000 * 3600 * 24 * 365.25);
console.log(age);
uneligible = age < 18;
};
now it's undefined in the syntax around the component and the component doesn't appear
<div>
{uneligible && (
<Alert variant="filled" severity="error">
This is an error alert — check it out!
</Alert>
)}
</div>
code sandox:https://codesandbox.io/s/serverless-wave-qyuc4?file=/src/App.js:602-767
I didn't use stateful variable because of that issue:conditional rendering is not working in my functional component
Have a look at react docs to understand how it'e ecosystem revolves around state. Your code should look something like this with the given details - https://codesandbox.io/s/quirky-buck-s2qvo
Instead of having a useEffect, you can call the same function when there is a certain event, say a click event on a button click.
Regarding your updated question - You were setting state again and again because each render due to setting a state will again call the state updater function and it will go on.... This is not what you want if you wanted a one-time initial render where you have no handler at all.
But now since you are going to handle the alert's visibility via a function handler, its your responsibility to add some sort of state to this component so that inside that handler you update the visibility state and display your Alert.
let allows you to declare variables that are limited to the scope of a block statement or expression on which it is used, unlike the var keyword, which declares a variable globally, or locally to an entire function regardless of block scope.
Just like const the let does not create properties of the window object when declared globally (in the top-most scope).
To achieve what you want you can use var / window.uneligible instead of let

How to periodically update a variable using meteor

I have a session variable that I want to update with a fixed periodicity. Say, I want this variable to be increased by 1 every 60 seconds.
It seems to me that the best place for doing this is inside the helpers section of the relevant template. I first tried to do this using setInterval as described here, but that didn't work (the function just didn't seem to repeat).
I then tried what I thought would be a straightforward solution, but this also doesn't work. See below. The helper variable 'currentPosition' is supposed to return the current minute of the day (plus an offset). However, it only does this when the template is first called and when the session variable 'offset' is changed in a function that's defined in the 'events' section, which responds to a click on a particular div (a 'next' button).
currentPosition: function () {
var d = new Date();
var h = d.getHours();
var m = d.getMinutes();
var w = h * 60 + m;
Session.set("position", w + Session.get("offset"));
return Session.get("position");
},
I would think that the above helper would actively update the value for 'currentPosition' every minute. Yet it does not.
So, my question is, how can I have a session variable change every, say, 60 seconds, increasing it by, say, 1, while the new value of the session variable is reflected within the app, when the variable is adjusted.
(If there's a straightforward and completely different solution which works in meteor, I'm not aware of it, so do point it out to me if I'm missing something obvious.)
Although you are using a reactive variable, it only gets set once - when the helper is first called. Therefore it doesn't run again. You need a function outside of the helper to set variable for you. Remember one important rule - helpers should never have side effects.
Here's a complete working example of how to create a timer:
html
<body>
{{> timer}}
</body>
<template name="timer">
<p>Total Seconds: {{seconds}}</p>
</template>
js
Template.timer.helpers({
seconds: function() {
return Template.instance().seconds.get();
}
});
Template.timer.created = function() {
var self = this;
this.seconds = new ReactiveVar(0);
this.handle = Meteor.setInterval((function() {
self.seconds.set(self.seconds.get() + 1);
}), 1000);
};
Template.timer.destroyed = function() {
Meteor.clearInterval(this.handle);
};

Javascript variable that always returns value of function

I'm pretty sure I know the answer to this (and that it is no), but is it possible to create a variable that always returns the value of a function without "calling" the variable?
I'm sick of an inactivity warning on a website I use. I look at it a few times a day, but I keep it open in case there's an update I need to look at. It automatically signs me out after 15 minutes using some javascript--the token isn't invalidated by a cookie expiring, nor is my session removed server-side--and the variable it checks is called last_user_action.
I'd like to make last_user_action always point to new Date().getTime();.
last_user_action = function() { new Date().getTime(); }
would work if I could easily change all the references to last_user_action to instead belast_user_action(), but I can't.
last_user_action = (function() { return new Date().getTime(); })();
only sets the value once.
So like I said, I doubt there's a way to do this, but if it is possible, how would I do it?
EDIT
It occurs to me now, it'd be easier to just run
window.setInterval(function() { last_user_action = new Date().getTime(); }, 1000 * 60 * 10);
in Chrome's javascript console.
Well, if you are sure it works that way, you could use setInterval every minute to set the value:
setInterval(function(){
last_user_action = new Date().getTime();
},60000)
Not that directly, but it would be trivial to just update the variable periodically.
function updateLastUserAction() {
last_user_action = new Date().getTime(); // or Date.now();
setTimeout(updateLastUserAction, 10000); // run again in 10 seconds
}
updateLastUserAction();
You can change the update period to suit you - since the update function is extremely lightweight, you can run it pretty often and it won't matter.
Assuming last_user_action is a global variable, that means it's actually a property of window and you can define a getter for that property.
Object.defineProperty(window, 'last_user_action', {
get: function() {
return new Date().getTime();
}
});
last_user_action; // 1412882205169
last_user_action; // 1412882206490
This would normally be a bad idea, but given you are hacking here, it doesn't seem so bad.
AFAIK you can't do that with a variable.
But you can do it with a property, using a getter:
var obj = {};
Object.defineProperty(obj, 'last_user_action', {
get: function() { return new Date().getTime(); }
});
obj.last_user_action; // Current date time

Expiring a javascript variable?

I saved some data returned from ajax in javascript variable. I would like to invalidate this variable after some time period, say one hour.
I can potentially write some setTimeout functions to handle this, but I just feel this is not optimal.
Another way is to save in cookie and set expiration, but the overhead may be unnecessary.
Is there other way that can handle this situation more elegantly?
Assuming the actual variable actually exists that long (the page stays open), just do what every cache does: save a timestamp and check for it.
var cache = { timestamp : null, data : null };
function setData(data) {
cache.data = data;
cache.timestamp = new Date;
}
function getData(maxAge) {
if (/* compare cache.timestamp to now - maxAge */) {
return null;
}
return cache.data;
}
Keep a variable that indicates when the value expires.
var foo = "bar";
var foo_expires_on = new Date(new Date().getTime() + 60 * 60 * 5); // +5 hours
deceze's answer is a more formal (monad) implementation.

Passed Variable not working with my function - Javascript

I've got text entry box and a countdown on the same page. I want to take the time from the box and enter it into the counter. I've got a variable back from the text box "setTime". I wanted to put that directly into my timeSplit function (to convert the time into seconds) but when I do I get an error that "time.split is not a function". What am I doing wrong here?
When I have a static variable enter the function (e.g. time = "12:12:12") everything works perfectly. - except its not using the right time
When I run the pop up alert on setTime before the timeSplit function I see my time like this "12:12:12" so its coming from the counter without a problem and I don't get a NaN error
Why would a time variable work when its static but not when its passed
I tried converting the setTime to a string but that just lead to NaN errors even when I tried to convert the sec variable back to an int.
I think this is the relevant code let me know if you need more.
var setTime = 0;
var $fromTime = $("#formEntry");
$("#setTime").off("click").on("click", function(){
setTime = $fromTime.val();
});
function timeSplit(){
//time = "12:12:12";
tt = time.split(":");
sec = tt[0]*3600+tt[1]*60+tt[2]*1;
return sec;
}
var time = setTime;
//var time = "12:12:12";
var sec = timeSplit(time);
Your function timeSplit() does not take any arguments. It needs to be timeSplit(time) so that JavaScript knows you are talking about calling the method .split() on an object called time rather than a function just called time.split().
If this wasn't just a typo (I've done that before), I suggest you read up some on function arguments and parameters so you know you understand how this works, it's really important.

Categories

Resources