i have 2 different javascript environments and want to create a library usable on both. to do that i want to use higher order functions to generate my functions, like so
try {
Maptool.chat.broadcast("")
var myFunc1 = genFunction1("env1");
}
catch(e){
if(e instanceof ReferenceError){
var myFunc1 = genFunction1("env2")
}
}
genFunction1 would return a function that i could call built from a function expression. there are only 2 ways i know to generate the function that is returned, it could be written similarly to the next code block with the if outside the inner function which would create a lot of code duplication as i would need to write everything in the function that is unchanged again.
function genFunction1(env){
if(env == "env1"){
return function () {return 3;}
}
else{
return function () {return 2;}
}
}
or with the if inside like the following code block
genFunction1(env){
return function (){
if(env=="env1"){
return 3;
}
return 2;
}
}
however if we use a object with a get property which logs when accessed we can see that the third code block calls a if for each call of myFunc1.
function genFunc1(obj){
return function (){
if(obj.env == "env2"){
console.log("3");
}
console.log("2");
}
}
const obj = {
get env() {
console.log("accessed property");
return "env2";
}
}
var myFunc1 = genFunc1(obj);
myFunc1();
myFunc1();
as previously said the earlier code block calls the get method once for each call of myFunc1(),but the environment won't change aside from the first time i check, is there any way to make the generated function not include a if and include the if only in the higher order function without duplicating code?
This is expected behavior as you are getting property from an object. Take a snapshot of the value before generating the function, like this.
function genFunc1(obj) {
var env = obj.env
return function() {
if (env == "env2") {
console.log("3");
}
console.log("2");
}
}
Related
I want to do something like this:
Say I already have a function named function()
If (function() == 2) {
console.log("you are great")
}
How do I do this the correct way?
You can't have function named function in JavaScript - it is reserved word. Fix to your problem would be give function a specific name when declaring it.
function test() {
// just example
return 2;
}
Then you can use it in if condition:
if (test() === 2) {
// do something
}
As mentioned in comments you have to name your function correctly (function is a reserved word in JS) and then check your condition in if statement. Here you can find simple example:
function getA() {
return 'a';
}
if(getA() === 'a'){
console.log('Success');
}
You can make global variable, call it with the function and return the value and call it inside the if condition.
For example:
// run this:
alert('Loading...');
// dont run this again:
alert('Loading...');
I don't want to ever repeat that.
How can I do this with convenience (preferably without using booleans)?
The standard way is to use a boolean flag.
But, if you have an aversion to booleans, you can do it by overwriting the function, thus ensuring it literally can never be called again.
function loadButOnlyOnce() {
console.log('This will only happen once!');
loadButOnlyOnce = function() {};
}
loadButOnlyOnce();
loadButOnlyOnce();
Your IDE will probably spew out warnings along the lines of "What are you doing, this is overwriting the function!". But it's your code, and you can do it if you want.
So, now you want a generic solution you can use with different functions? You can do this like so:
function allowOnlyOneCall(f) {
return function() {
f.apply(this, arguments);
f = function() {};
}
}
function myMethod(p1) {
console.log('myMethod is being invoked. p1 = ' + p1);
}
myMethod = allowOnlyOneCall(myMethod);
myMethod(5);
myMethod(5);
Here is one clean implementation you could use so you can avoid the usage of booleans for every single task you don't want to repeat:
var cache = [];
function do_once(task, fn) {
if(cache.indexOf(task) == -1) { // shorthand: !~cache.indexOf(task)
cache.push(task);
return fn();
}
}
Usage:
var alertLoading = alert.bind(null, "Loading...");
do_once("alert_loading", alertLoading); // will run
// later on...
do_once("alert_loading", alertLoading); // will not run again
This works as long as you give each task you don’t want to repeat a different name. Regardless of the function provided as the second argument to do_once, it will not run as long as do_once has already been called using the same task name.
First create a variable to store whether the function has already run or not (such as hasRun). Then simply store your functionality inside an if condition which checks that this variable is false. You would need to update this variable after running the logic for the first time.
This can be seen in the following:
hasRun = false;
document.getElementsByTagName('button')[0].addEventListener('click', function() {
if (!hasRun) {
console.log('Loading...'); // Gets run once
hasRun = true; // Set the flag to true so the conditional doesn't get entered again
} else {
console.log('The function already ran!'); // Runs every subsequent time
}
})
<button>Click me</button>
If you want a factory function that memoizes the result of calling a function with a single primitive value as a parameter, you should use a Map:
const once = (() => fn => {
const cache = new Map()
return value => {
if (!cache.has(value)) {
cache.set(value, fn(value))
}
return cache.get(value)
}
})()
function verboseSquare (value) {
console.log('expensive calculation')
return value * value
}
const squareOnce = once(verboseSquare)
console.log(squareOnce(4))
console.log(squareOnce(4)) // skipped work
console.log(squareOnce(5))
console.log(squareOnce(5)) // skipped work
I need to check some conditions before calling functions and those functions are calling from different js files like index.js or app.js.
What will be the best way to check that conditions before calling others? Think about you are doing something like authentication, if user is authenticated then call the function. I need to check that condition for 30 functions.
Instead of making changes on the functions I need to write one function/attribute/whatever and that needs to effect others.
file1.js:
function1
function2
function3
...
function30
file2.js:
file1.function1();
file3.js:
file1.function15();
To give an example of my suggestion in the comments, this is a simple way to wrap each function with an auth check without adding too much clutter to your calls.
// Some mock up of you existing code
var authenticated = true;
function thing1() { alert(1); }
function thing2() { alert(2); }
function thing3() { alert(3); }
// New code
function checkAuthAndRun(func) {
if (authenticated) {
func();
} else {
console.log("User is not allowed to do this");
}
}
// Calling your functions
checkAuthAndRun(thing1);
checkAuthAndRun(thing2);
checkAuthAndRun(thing3);
Example with parameters
// Some mock up of you existing code
var authenticated = true;
function thing1() {alert(1); }
function thing2(a) { alert(a); }
function thing3(a, b) { alert(a + b); }
// New code
function checkAuthAndRun(func) {
if (authenticated) {
// This line will need to have as many arguments[x] parameters as the function
// with the most parameters that you will call through this method
func(arguments[1], arguments[2]);
} else {
console.log("User is not allowed to do this");
}
}
// Calling your functions
checkAuthAndRun(thing1);
checkAuthAndRun(thing2, "Parameter 1");
checkAuthAndRun(thing3, "Parameter 1", "Parameter 2");
If I've understood your problem then I guess you don't want if-else or switch to clutter your code and you want a cleaner way to do this. What I would've done is, made a configuration file and executed it in the following way:
import {function1, function2, function3, function4 ...} from './functions';
const FUNCTIONS_TO_RUN = {
auth: () => {
function1();
function2();
...
},
noAuth: () => {
function3();
function4();
...
},
....
};
while calling them, I would just do as :
FUNCTIONS_TO_RUN[conditionType]();
This is not the exact solution but an idea how you can implement it in a cleaner way.
conditionType can be auth or noAuth in this case.
You may use && to short-circuit the statement.
Like, condition && fun() , fun() will be called only when conditon is true.
This is how && operator works in JS. if the first expression is wrong then it won't execute the rest of them otherwise it returns the value returned by the following expression(s), of course after executing them.
function auth(condition) {
return condition;
}
function isOdd(n) {
console.log(n," is odd ",n %2 == 0);
}
auth(false) && isOdd(3); //won't call
auth(false) && isOdd(4); //won't call
auth(true) && isOdd(5);
auth(true) && isOdd(6);
I'm trying to simplify a line of code I do use everytime:
if (we_need_to_exit) { op(); return; }
Do I have a chance to define a function, something like this:
function my_return (x) {
x.op();
x.return;
}
and use it like:
if (we_need_to_exit) { my_return(this); }
Is it possible to define such a function?
Edit
Best simple solution that fits in my case is the following:
if (we_need_to_exit) { return op(); }
no, once you call my_return, that return inside of my_return is to return from within my_return.
You can probably do what you want by:
if (we_need_to_exit) { return my_fn(this); }
and your my_fn will be:
function my_fn (x) {
x.op();
// return any value you want, or use "return;" or just omit it
}
Why this won't work:
function my_return (x) {
x.op();
x.return; //[1] [2]
}
//-----and use it like-------------------
if (we_need_to_exit) { my_return(this); //[3]}
It means creating a return property on x, it won't return.
replacing x.return; with return; will return from the function, not from outside of it's call (at [3], which is your objective).
'my_return(this)' "this" will be set to the object calling the function the "if statement" is in.
function x(){
console.log(this); //shows the global object (window, if run in a browser)
}
var y = {
fruit:"apple",
x:function(){
console.log(this); // shows the calling object
}
};
x();
y.x();
I've found myself using this pattern recently to do initialization that should only ever run once:
function myInit() {
// do some initialization routines
myInit = function () {return;};
}
This way if I had two different methods which required something myInit did, it would ensure that it would only run once. See:
function optionA() { myInit(); doA(); }
function optionB() { myInit(); doB(); }
In the back of my head I feel like I'm missing something and I shouldn't be doing this. Is there any reasons why I shouldn't write code like this?
Is there any reasons why I shouldn't write code like this?
One reason is that the function will only work as you intend in the scope it was defined in. E.g. if you pass the function somewhere else, it won't be affected by your modifications and in the worst case would create an implicit global variable. E.g.
function myInit() {
// do some initialization routines
myInit = function () {return;};
}
function foo(init) {
init();
init();
}
foo(myInit);
The better approach is to encapsulate the whole logic:
var myInit = (function() {
var initialized = false;
return function() {
if (initialized) return;
initialized = true;
// do some initialization routines
};
}());
Now, no matter how, where and when you call myInit, it will do the initialization step only once.
May be you can do something like,
var myInitCalled = false; // Global declaration of flag variable
function myInit() {
// do some initialization routines
myInitCalled = true; // Setting the global variable as true if the method is executed
myInit = function () {return;};
}
Then in your methods, you can probably use:
function optionA()
{
if(!myInitCalled ) // Checking if first time this is called.
{myInit();}
doA();
}
function optionB()
{
if(!myInitCalled )
{myInit();}
doB();
}
This will ensure that myInit is called only once!!