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.
Related
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 👍🏻
Questions are as follows:
The first time you call the add, it will return 1;
the second time you call, it returns 2;
Can only be written in function
var add = function () {
// start only
// end
};
console.log(add()); // 1
console.log(add()); // 2
The current idea is that a global variable is needed
So the current way of writing
But this way of writing does not meet the requirements
var add = (function () {
let counter=0
return function () {
counter += 1; return counter;}
}();
I don't know how to adjust the code to solve this question thank you
somethig like this?
var add = {
time: 0,
call: () => {
add.time++;
console.log(add.time);
}
};
add.call(); // 1
add.call(); // 2
I'd do it like this. It implicitely creates a global variable, which is dirty as hell, but it meets the (strange) requirements.
var add = function () {
if(typeof a === "undefined") a = 0;
return ++a;
};
console.log(add()); // 1
console.log(add()); // 2
All the solutions that came to mind:
Use a property assigned to the function
// in JS, a function is also an object; you can assign properties to it.
function add() {
if (add.value === undefined) add.value = 0;
return ++add.value;
}
console.log(add());
console.log(add());
Create a local scope
var add = (function() {
var value = 0;
return function() {
return ++value;
};
})();
console.log(add());
console.log(add());
Use the global scope
function add() {
if (window._currentValue === undefined) window._currentValue = 0;
return ++window._currentValue;
}
console.log(add());
console.log(add());
I think that the first solution may be of particular interest to you.
You can create a parameter inside window object. But I prefer the naxsi answer.
var add = function () {
if (window.added === undefined) window.added = 0;
window.added += 1;
return window.added;
};
console.log(add()); // 1
console.log(add()); // 2
The purpose of the example code below is to be able to restrict a function from printing something via console.log (a loop in this case) if the function is executed twice.
However, the function uses the global variable "condition" and I want to find a way to avoid this. I've been playing around with workarounds, but to no avail. Also, I have checked sources online, but relate to other more complex examples which are beyond my level. This is a simpler example, but haven't been able to crack this.
Grateful for some guidance. Thanks.
let condition = false;
const testFunc = function (value) {
for (let i = 0; i < 10; i++) {
if (!condition) {
console.log(value + i);
}
}
condition = true;
};
testFunc(5);
testFunc(5);
The usual answer is to create yet another scope to hold the state:
function once(fn) {
let called = false
return function(...args) {
if (!called) {
fn(...args)
called = true
}
}
}
const test = once(function() {
console.log('hello')
})
test() // hello
test() // nothing
Thanks for your feedback - I considered the use of using closure by way of returning a function within another.
Would this be a viable option in order to avoid a global variable? Note that "func" needs to be declared globally -
const testFuncEncaps = function (value) {
let trueOrFalse = false;
return function () {
for (let i = 0; i < 10; i++) {
if (!trueOrFalse) {
console.log(value + i);
}
}
trueOrFalse = true;
};
};
let func = testFuncEncaps(5);
func();
func();
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.
1
document.onkeydown = function(a) {
//
};
2
var a = function(a) {
//
};
document.onkeydown = a;
I had the idea that maybe in the first case, the function needs to be re-parsed (for lack of better word) every time the event happens, whereas in the second case it just points to the already parsed function.
If not this, maybe there is another (any) difference.
Update
If I understand this correctly, there is a difference between these, and it's better to use the second.
1
var a = window.onresize = function() {
//
};
// ...
a();
2
var a = function() {
//
};
window.onresize = a;
// ...
a();
In your current form, there's no difference (the anonymous function might even be a tad faster). The only advantage of storing the function separately is when you do it in a loop (or if the function may have other uses).
For example:
var elements = document.getElementsByTagName('input');
for ( var i = 0; i < elements.length; i++ ) {
element[i].onkeydown = function () {
// whatever
}
}
every element will get its own copy of the function, which increases your page's memory usage.
If you instead store the function outside the loop:
var elements = document.getElementsByTagName('input');
var eventListener = function () {
// whatever
};
for ( var i = 0; i < elements.length; i++ ) {
element[i].onkeydown = eventListener;
}
they'll all share the same function.
P.S. As pointed out by #VisioN, a better way would be to use addEventListener. The same rules apply there too.