I'm solving an exercise that is intended to use closures. You must create a function that returns a function that will store a value and, when you reuse it, add the new value to the saved one.
const firstValue = myFunction(3);
const secondValue = firstValue(4);
// result => 7
this is the code that I'm using to practice closures:
function addNumbers(num) {
let storage = 0
let n = num
function adding(n) {
storage += n;
return storage
}
return adding(n)
}
let firstAttemp = addNumbers(4)
let secondAttemp = firstAttemp(3)
console.log(firstAttemp)
this throw an error "Uncaught TypeError: firstAttemp is not a function"
const addNumbers = (a) => (b) => a + b
It's called currying, more details here.
P.S.
If you want to use function syntax, it will look like this:
function addNumbers(a) {
return function (b) {
return a + b
}
}
As #skara stated in their comment, return adding(n) returns the result of calling adding instead of returning the function so that it may be called later with firstAttemp(3).
Unfortunately though it still doesn't work because you don't actually assign the value passed to addNumber to be added later.
function addNumbers(num) {
let storage = 0;
let n = num;
function adding(n) {
storage += n;
return storage;
}
return adding;
}
let firstAttemp = addNumbers(4);
let secondAttemp = firstAttemp(3);
console.log(firstAttemp);
console.log(secondAttemp); // 3! 😢
You don't actually need to manually save the value of num to a variable as it is captured in the closure arround adding that is being returned.
function addNumbers(num) {
function adding(n) {
return num + n;
return storage;
}
return adding;
}
let firstAttemp = addNumbers(4);
let secondAttemp = firstAttemp(3);
console.log(secondAttemp); // 7 👍🏻
I tried to isolate the problem as much as from my original code. The following outputs "2" to the console:
class Observable {
constructor() {
this.listeners = [];
}
on(eventName, callback) {
this.listeners.push(callback);
}
fireEvent() {
let me = this;
setTimeout(() => {
me.listeners.forEach(callback => {
callback();
});
}, 100);
}
}
let observable = new Observable();
let x = 1;
observable.on("event", () => {
console.log(x);
})
observable.fireEvent();
x = 2;
What I really wanted to do was to make callback print "1" (the value before the x is changed by another piece of code). So after a long debugging session I did something like this:
class Observable {
constructor() {
this.listeners = [];
}
on(eventName, callback) {
this.listeners.push(callback);
}
fireEvent() {
let me = this;
setTimeout(() => {
me.listeners.forEach(callback => {
callback();
});
}, 100);
}
}
let observable = new Observable();
let x = 1;
var unboundFunction = () => {
console.log(this);
};
var boundFunction = unboundFunction.bind(x);
observable.on("event", boundFunction);
observable.fireEvent();
x = 2;
For reasons I don't understand second code prints the Window object in Chrome console, but the similar code works as I want in my project. I am guessing because there was no "this" before in the original code, but "this" refers to the "window" in chrome so it works differently when run in console.
Is this the right way to do what I want?
I think the easiest way would be to create a local block-scoped constant that gets assigned the current value of x:
class Observable {
constructor() {
this.listeners = [];
}
on(eventName, callback) {
this.listeners.push(callback);
}
fireEvent() {
setTimeout(() => {
this.listeners.forEach(callback => callback());
}, 100);
}
}
let observable = new Observable();
let x = 1;
{
const innerX = x;
observable.on("event", () => {
console.log(innerX);
});
}
observable.fireEvent();
x = 2;
For reasons I don't understand second code prints the Window object in Chrome console
Because the unboundFunction is an arrow function defined on the top level, this will always refer to either the global object, or to undefined in strict mode.
If it refers to something else in your project, the unboundFunction must not be declared on the top level. .binding an arrow function doesn't change its this.
I wrote a callback helper, that lets me group multiple callbacks into one function variable:
function chainCallbacks() {
var callbacks = arguments;
return function () {
for(var i = 0; i < callbacks.length; i++) {
if(callbacks[i] != null) {
callbacks[i].apply(null, arguments);
}
}
};
}
this works, but I'm wondering if there are any javascript libraries that provide the same functionality? or even better, something that simulates the .NET "event" pattern?
myEvent+=myCallback;
I have modified your chainCallbacks function. You can test below code in JS console (I'm using Chrome -works fine), and check the result.
var result = 0;
function a() {
result += 5;
console.log(result);
_next();
}
function b() {
result += 10;
console.log(result);
_next();
}
function c() {
result += 20;
console.log(result);
_next();
}
function chainCallbacks() {
var _this = this;
var _counter = 0;
var _callbacks = arguments;
var _next = function() {
_counter++;
if(_counter < _callbacks.length) {
_callbacks[_counter].apply(_this);
}
};
_this._next = _next;
return function() {
if(_callbacks.length > 0) {
_callbacks[0].apply(_this);
}
};
}
var queue = chainCallbacks(a, b, c);
queue();
Idea is simple - you call _next() whenever your callback function has finished executing, and you want to jump to another. So you can call _next() e.g. after some jQuery animation as well, and this way you will preserve the order of the functions.
If you want to replace a callback with one that calls the original as well as some others, I'd probably just do something like this:
Requirejs.config.callback = function(orig) {
var fns = [orig, first, second, third];
return function() {
fns.forEach(function(fn) { fn.apply(null, this); }, arguments);
};
}(Requirejs.config.callback);
But if you're doing this often, I think your solution will be as good as it gets. I don't see need for a library.
Requirejs.config.callback = chainCallbacks(Requirejs.config.callback, first, second, third)
A library can't do anything to extend language syntax in JavaScript. It's limited to what's available... no operator overloading or anything.
I need to create a function which can be executed only once, in each time after the first it won't be executed. I know from C++ and Java about static variables that can do the work but I would like to know if there is a more elegant way to do this?
If by "won't be executed" you mean "will do nothing when called more than once", you can create a closure:
var something = (function() {
var executed = false;
return function() {
if (!executed) {
executed = true;
// do something
}
};
})();
something(); // "do something" happens
something(); // nothing happens
In answer to a comment by #Vladloffe (now deleted): With a global variable, other code could reset the value of the "executed" flag (whatever name you pick for it). With a closure, other code has no way to do that, either accidentally or deliberately.
As other answers here point out, several libraries (such as Underscore and Ramda) have a little utility function (typically named once()[*]) that accepts a function as an argument and returns another function that calls the supplied function exactly once, regardless of how many times the returned function is called. The returned function also caches the value first returned by the supplied function and returns that on subsequent calls.
However, if you aren't using such a third-party library, but still want a utility function (rather than the nonce solution I offered above), it's easy enough to implement. The nicest version I've seen is this one posted by David Walsh:
function once(fn, context) {
var result;
return function() {
if (fn) {
result = fn.apply(context || this, arguments);
fn = null;
}
return result;
};
}
I would be inclined to change fn = null; to fn = context = null;. There's no reason for the closure to maintain a reference to context once fn has been called.
Usage:
function something() { /* do something */ }
var one_something = once(something);
one_something(); // "do something" happens
one_something(); // nothing happens
[*] Be aware, though, that other libraries, such as this Drupal extension to jQuery, may have a function named once() that does something quite different.
Replace it with a reusable NOOP (no operation) function.
// this function does nothing
function noop() {};
function foo() {
foo = noop; // swap the functions
// do your thing
}
function bar() {
bar = noop; // swap the functions
// do your thing
}
Point to an empty function once it has been called:
function myFunc(){
myFunc = function(){}; // kill it as soon as it was called
console.log('call once and never again!'); // your stuff here
};
<button onClick=myFunc()>Call myFunc()</button>
Or, like so:
var myFunc = function func(){
if( myFunc.fired ) return;
myFunc.fired = true;
console.log('called once and never again!'); // your stuff here
};
// even if referenced & "renamed"
((refToMyfunc)=>{
setInterval(refToMyfunc, 1000);
})(myFunc)
UnderscoreJs has a function that does that, underscorejs.org/#once
// Returns a function that will be executed at most one time, no matter how
// often you call it. Useful for lazy initialization.
_.once = function(func) {
var ran = false, memo;
return function() {
if (ran) return memo;
ran = true;
memo = func.apply(this, arguments);
func = null;
return memo;
};
};
Talking about static variables, this is a little bit like closure variant:
var once = function() {
if(once.done) return;
console.log('Doing this once!');
once.done = true;
};
once(); // Logs "Doing this once!"
once(); // Logs nothing
You could then reset a function if you wish:
once.done = false;
once(); // Logs "Doing this once!" again
You could simply have the function "remove itself"
function Once(){
console.log("run");
Once = undefined;
}
Once(); // run
Once(); // Uncaught TypeError: undefined is not a function
But this may not be the best answer if you don't want to be swallowing errors.
You could also do this:
function Once(){
console.log("run");
Once = function(){};
}
Once(); // run
Once(); // nothing happens
I need it to work like smart pointer, if there no elements from type A it can be executed, if there is one or more A elements the function can't be executed.
function Conditional(){
if (!<no elements from type A>) return;
// do stuff
}
var quit = false;
function something() {
if(quit) {
return;
}
quit = true;
... other code....
}
simple decorator that easy to write when you need
function one(func) {
return function () {
func && func.apply(this, arguments);
func = null;
}
}
using:
var initializer= one( _ =>{
console.log('initializing')
})
initializer() // 'initializing'
initializer() // nop
initializer() // nop
try this
var fun = (function() {
var called = false;
return function() {
if (!called) {
console.log("I called");
called = true;
}
}
})()
From some dude named Crockford... :)
function once(func) {
return function () {
var f = func;
func = null;
return f.apply(
this,
arguments
);
};
}
Reusable invalidate function which works with setInterval:
var myFunc = function (){
if (invalidate(arguments)) return;
console.log('called once and never again!'); // your stuff here
};
const invalidate = function(a) {
var fired = a.callee.fired;
a.callee.fired = true;
return fired;
}
setInterval(myFunc, 1000);
Try it on JSBin: https://jsbin.com/vicipar/edit?js,console
Variation of answer from Bunyk
Here is an example JSFiddle - http://jsfiddle.net/6yL6t/
And the code:
function hashCode(str) {
var hash = 0, i, chr, len;
if (str.length == 0) return hash;
for (i = 0, len = str.length; i < len; i++) {
chr = str.charCodeAt(i);
hash = ((hash << 5) - hash) + chr;
hash |= 0; // Convert to 32bit integer
}
return hash;
}
var onceHashes = {};
function once(func) {
var unique = hashCode(func.toString().match(/function[^{]+\{([\s\S]*)\}$/)[1]);
if (!onceHashes[unique]) {
onceHashes[unique] = true;
func();
}
}
You could do:
for (var i=0; i<10; i++) {
once(function() {
alert(i);
});
}
And it will run only once :)
Initial setup:
var once = function( once_fn ) {
var ret, is_called;
// return new function which is our control function
// to make sure once_fn is only called once:
return function(arg1, arg2, arg3) {
if ( is_called ) return ret;
is_called = true;
// return the result from once_fn and store to so we can return it multiply times:
// you might wanna look at Function.prototype.apply:
ret = once_fn(arg1, arg2, arg3);
return ret;
};
}
If your using Node.js or writing JavaScript with browserify, consider the "once" npm module:
var once = require('once')
function load (file, cb) {
cb = once(cb)
loader.load('file')
loader.once('load', cb)
loader.once('error', cb)
}
If you want to be able to reuse the function in the future then this works well based on ed Hopp's code above (I realize that the original question didn't call for this extra feature!):
var something = (function() {
var executed = false;
return function(value) {
// if an argument is not present then
if(arguments.length == 0) {
if (!executed) {
executed = true;
//Do stuff here only once unless reset
console.log("Hello World!");
}
else return;
} else {
// otherwise allow the function to fire again
executed = value;
return;
}
}
})();
something();//Hello World!
something();
something();
console.log("Reset"); //Reset
something(false);
something();//Hello World!
something();
something();
The output look like:
Hello World!
Reset
Hello World!
A simple example for turning on light only once.
function turnOnLightOnce() {
let lightOn = false;
return function () {
if (!lightOn) {
console.log("Light is not on...Turning it on for first and last time");
lightOn = true;
}
};
}
const lightOn = turnOnLightOnce();
lightOn() // Light is not on...Turning it on for first and last time
lightOn()
lightOn()
lightOn()
lightOn()
https://codesandbox.io/s/javascript-forked-ojo0i?file=/index.js
This happens due to closure in JavaScript.
function once (fn1) {
var ran = false
var memo = null
var fn = function(...args) {
if(ran) {return memo}
ran = true
memo = fn1.apply(null, args)
return memo
}
return fn
}
I'm using typescript with node and it was #I Hate Lazy's answer that inspired me. I just assigned my function to a noop function.
let printName = (name: string) => {
console.log(name)
printName = () => {}
}
printName('Sophia') // Sophia
printName('Nico') // Nothing Happens
https://jsbin.com/yuzicek/edit?js,console
FOR EVENT HANDLER
If the function is a callback for an event listener, there is already a built-in option in the addEventListner method for just executing the callback once.
It can accept 3 parameters
Type
callback
options
options is an object that has a property called once
ex:
const button = document.getElementById('button');
const callbackFunc = () => {
alert('run')
}
button.addEventListener('click', callbackFunc, { once: true })
<button id="button">Click Once</button>
Trying to use underscore "once" function:
var initialize = _.once(createApplication);
initialize();
initialize();
// Application is only created once.
http://underscorejs.org/#once
var init = function() {
console.log("logges only once");
init = false;
};
if(init) { init(); }
/* next time executing init() will cause error because now init is
-equal to false, thus typing init will return false; */
if (!window.doesThisOnce){
function myFunction() {
// do something
window.doesThisOnce = true;
};
};
If you're using Ramda, you can use the function "once".
A quote from the documentation:
once Function
(a… → b) → (a… → b)
PARAMETERS
Added in v0.1.0
Accepts a function fn and returns a function that guards invocation of fn such that fn can only ever be called once, no matter how many times the returned function is invoked. The first value calculated is returned in subsequent invocations.
var addOneOnce = R.once(x => x + 1);
addOneOnce(10); //=> 11
addOneOnce(addOneOnce(50)); //=> 11
keep it as simple as possible
function sree(){
console.log('hey');
window.sree = _=>{};
}
You can see the result
JQuery allows to call the function only once using the method one():
let func = function() {
console.log('Calling just once!');
}
let elem = $('#example');
elem.one('click', func);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div>
<p>Function that can be called only once</p>
<button id="example" >JQuery one()</button>
</div>
Implementation using JQuery method on():
let func = function(e) {
console.log('Calling just once!');
$(e.target).off(e.type, func)
}
let elem = $('#example');
elem.on('click', func);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div>
<p>Function that can be called only once</p>
<button id="example" >JQuery on()</button>
</div>
Implementation using native JS:
let func = function(e) {
console.log('Calling just once!');
e.target.removeEventListener(e.type, func);
}
let elem = document.getElementById('example');
elem.addEventListener('click', func);
<div>
<p>Functions that can be called only once</p>
<button id="example" >ECMAScript addEventListener</button>
</div>
Tossing my hat in the ring for fun, added advantage of memoizing
const callOnce = (fn, i=0, memo) => () => i++ ? memo : (memo = fn());
// usage
const myExpensiveFunction = () => { return console.log('joe'),5; }
const memoed = callOnce(myExpensiveFunction);
memoed(); //logs "joe", returns 5
memoed(); // returns 5
memoed(); // returns 5
...
You can use IIFE. IIFE means Immediately Invoked Function Expression and the result is to call a function only once by the time is created.
Your code will be like this:
(function () {
//The code you want to execute only one time etc...
console.log("Hello world");
})()
Additionally, this way the data in the function remains encapsulated.
Of course and you can return values from the function and stored them into a new variable, by doing:
const/let value = (function () {
//The code you want to execute only one time etc...
const x = 10;
return x;
})()
function x()
{
let a=0;
return function check()
{
if(!a++)
{
console.log("This Function will execute Once.")
return;
}
console.log("You Can't Execute it For the Second Time.")
return;
}
}
z=x()
z() //Op - This Function will execute once
z() //OP - You can't Execute it for the second time.
I find it useful to just have a simple function that just returns true once, so you can keep the side effects higher up.
let once = () => !! (once = () => false);
once() // true
once() // false
Use like this:
if (once()) {
sideEffect()
}
This exploits the fact that you can coerce an assignment expression to return true while changing the same function into a function that returns false.
If you must have it execute a function, it can be adapted using a ternary:
let once = (x) => !! (once = () => false) ? x() : false;
Now it accepts a single function as an argument. Fun fact, the second false is never reached.
// This is how function in JavaScript can be called only once
let started = false;
if (!started) {
start() { // "do something" }
}
started = true;
}
I'm using Node.js.
Could you tell where is the advantage of using this (closure):
function sayHello() {
var num = 0;
var sayAlert = function (val) {
num++;
console.log(num);
}
return sayAlert;
}
over this old classic one:
function sayHello2() {
var num = 0;
this.sayAlert = function (val) {
num++;
console.log(num);
}
}
var ee1 = sayHello();
ee1(5);
ee1(6);
var ee2 = new sayHello2();
ee2.sayAlert(5);
ee2.sayAlert(6);
(shorter code perhaps for closure and more "JavaScipt way"?)
It seems like what you're really after is a function with a static counter. For that you can just use an immediately executing function.
var say = (function() {
var num = 0;
return function (val) {
// Not sure why you're passing val here, it's not used
num++;
console.log(num);
}
})();
Unless what you want is multiple counters, then you should use better names so it's clear to all who read it.
function createCounter() {
var num = 0;
return function () {
console.log(++num);
}
}
In the second example, you've implemented the same thing by using a counter on the closure of the constructor let's call it Speaker.
function Speaker() {
var num = 0;
this.sayAlert = function() {
console.log(++num);
}
}
They all do kind of the same thing
say(); say(); //outputs 1,2
var speaker = new Speaker();
speaker.sayAlert(); speaker.sayAlert(); //outputs 1,2
var speaker2 = new Speaker();
speaker2.sayAlert(); speaker2.sayAlert(); //outputs 1,2
var ctr1 = createCounter(); ctr1(); ctr1(); //outputs 1,2
var ctr2 = createCounter(); ctr2(); ctr2(); //outputs 1,2
Which one to use depends on whether you want a function or an object. And mostly whether you prefer to write functional or OO code.
Neither is better. It depends on your needs.
They're nearly identical, except that one returns a function and the other returns an object that holds a function.
The second example allows to have more than one method.