Why this is working:
var a = () => {
var print = function(i) { console.log(i); return this; }
var print2 = function(i) { console.log(i); return this; }
return { print:print , print2:print2 }
}
a().print(5).print2(5);
this is also working:
var b = () => {
var print = (i) => { console.log(i); return this; }
return { print:print}
}
b().print('Arrow function works');
while this is not working:
var b = () => {
var print = (i) => { console.log(i); return this; }
var print2 = function(i) { console.log(i); return this; }
return { print:print , print2:print2 }
}
b().print(5).print2(5);
https://jsfiddle.net/Imabot/1gt2kxfh/14/
It's all due to arrow functions behavior(docs)
Step by step explanation:
var b = () => {
// 1
var print = (i) => { console.log(i); return this; }
var print2 = function(i) { console.log(i); return this; }
return { print:print , print2:print2 }
}
const res = b()
// 2
const secondRes = res.print(5)
// 3
secondRes.print2(5);
here print function saves this reference from the outer scope, so this can't be reassigned anymore
now print function is not using this reference that comes from res variable, because this has already been attached to print function above
as a result secondRes is not going to reference to the object that was returned by b function. But it will use this reference that is attached to print function. And finally because secondRes doesn't have print2 property - it throws
Hope it helps <3
In a non-arrow function, the value of this depends on how the function is called. If the function is called as a member of an object, this refers to this object:
someObj.myFunction() // inside myFunction this will point to someObj
In contrast, the arrow functions do not affect this. So whithin an arrow function the value of this is whatever it is in the enclosing scope.
The answer from Lex82 gives the why. If you want to return the functions, so you can use function chaining:
var b = () => {
var print = (i) => { console.log(i); return { print:print , print2:print2 }; }
var print2 = function(i) { console.log(i); return this; }
return { print:print , print2:print2 }
}
b().print(5).print2(5);
Related
I get confuse about function while doing study javascript.
I think that's same thing about function.
What the difference?
var getCode = function() {
apiCode = '0]Eal(eh&2';
return function() {
return apiCode;
};
}
var getCode = (function() {
apiCode = '0]Eal(eh&2';
return function() {
return apiCode;
};
}();
It's the same difference as between f and f(). The former is a function (assuming f refers to a function), the latter is a function call.
The "II" part in IIFE means "immediately invoked", i.e. you don't just have a function expression, you immediately call it by putting () after it.
var getCode = function() {
apiCode = '0]Eal(eh&2';
return function() {
return apiCode;
};
}
This assigns function() { apiCode = '0]Eal(eh&2'; return function() { return apiCode; }; } to getCode.
var getCode = (function() {
apiCode = '0]Eal(eh&2';
return function() {
return apiCode;
};
}();
Here we have function () { ... }(), so this immediately calls the outer function and assigns the return value to getCode, which is function() { return apiCode; }.
Perhaps a simpler example:
var x = function () { return 42; }; // x is a function that, when called, returns 42
var y = function () { return 42; }(); // y is 42
Simply put, an IIFE executes the function once and puts the returning value to the variable.
E.g;
let res = (function sum(){
return 1+2;
})();
console.log(res);
On the other hand, function expression just holds a reference to the function and needs to be invoked.
E.g.;
let res = function sum(){
return 1+2;
};
console.log(res());
Can't figure out how to return result of the nested function in arrow function.
How to express this one (works fine):
var stopEating = (function() {
var loadedStomach = false;
return function() {
if(!loadedStomach){
loadedStomach = true;
console.log('Stop eating');
}};
})();
as an arrow function (doesn't work properly):
const stopEating = () => {
let loadedStomach = false;
return () => {
if(!loadedStomach) {
loadedStomach = true;
console.log('Its enough eating!');
}};
};
You need to call the function in order to get the results, thus, adding the parentheses at the end.
const stopEating = (() => {
let loadedStomach = false;
return () => {
if(!loadedStomach) {
loadedStomach = true;
console.log('Its enough eating!');
}
};
})();
Into the first example, you created Immediately Invoked Function Expression (IIFE).
It's a JavaScript function that runs as soon as it is defined. That's why you receive internal function, which prints "Stop Eating".
To realize this pattern you just need to wrap arrow function:
const stopEating = (() => {
let loadedStomach = false;
return () => {
if(!loadedStomach) {
loadedStomach = true;
console.log('Its enough eating!');
}
};
})();
I am trying to write a memoization function, but keep getting the following error.
Error - "TypeError: getNthFibonacciNo is not a function
at dabebimaya.js:28:38
at https://static.jsbin.com/js/prod/runner-4.1.4.min.js:1:13924
at https://static.jsbin.com/js/prod/runner-4.1.4.min.js:1:10866"
How can I find this error in my code? I have tried googling the error with no avail. Please point out any additional errors too if possible.
function memoize(fn) {
var cache = {};
if (cache[arguments[0]]!==undefined) {
return cache[arguments[0]];
}
else {
var value = fn.apply(this, arguments);
cache[arguments[0]] = value;
return value;
}
}
var getNthFibonacciNo = memoize(function(n){
//1,1,2,3,5,8,13,21,34
if(i<=2)
return 1;
var fib = [0,1,1];
for(var i=3;i<=n;i++) {
fib[i] = fib[i-2]+fib[i-1];
}
return fib[n];
});
console.log(getNthFibonacciNo(7));
Your memoize function isn't returning a function.
function memoize(fn) {
var cache = {};
return function() {
if (cache[arguments[0]]!==undefined) {
return cache[arguments[0]];
}
else {
var value = fn.apply(this, arguments);
cache[arguments[0]] = value;
return value;
}
}
}
now returns a function so that it can be called multiple times.
Usage
function test(a) {
console.log('calling test', a);
return a + 1;
}
const memoized = memoize(test);
memoized(1); // prints calling test and returns 2
memoized(1); // returns 2
memoized(2); // prints calling test and returns 3
I managed to fix my code after suggestions by AnilRedshift. Below is the fixed code.
function memoize(fn) {
var cache = {};
return function() {
var key = JSON.stringify(arguments);
if (cache[key]) {
console.log('cache used');
return cache[key];
}
else {
var value = fn.apply(this, arguments);
cache[key] = value;
console.log('cache not used');
return value;
}
};
}
var fibonacciMemoized = memoize(function(n) {
//1,1,2,3,5,8,13,21,34
if(i<=2)
return 1;
var fib = [0,1,1];
for(var i=3;i<=n;i++) {
fib[i] = fibonacciMemoized(i-2)+fibonacciMemoized(i-1);
}
return fib[n];
});
console.log(fibonacciMemoized(7));
console.log(fibonacciMemoized(9));
I wanted to create a local function variable for a specific use case without polluting my global object scope. I will be calling doThis() multiple times, but want to keep the local counter value.
So, do this:
TaskHandler = {
doThis : function () {
myVariable+= (myVariable) ? var myVariable = 0;
doSomethingWithVariable(myVariable);
// OR
var myVariable = myVariable+=1 || 0;
// OR
var myVariable = (myVariable) ? myVariable+=1 : 0;
}
Instead of:
TaskHandler = {
myVariable : 0,
doThis : function () {
this.myVariable++;
doSomethingWithVariable(this.myVariable);
}
Is this possible?
TaskHandler = {
doThis : function (requirement) {
var track_index = (function () {
var myVariable = 0;
return function () {
++myVariable;
}
})();
doSomethingWithVariable(track_index);
},
}
TaskHandler = {
doThis : function () {
(function () {
console.log('called'); // This is called
var myVariable = 0;
return function () {
++myVariable;
console.log(myVariable); // This is NOT called
}
})();
}
}
Last edit:
TaskHandler = {
someFunction : function (myObject) {
this.doThis(myObject).counter();
},
doThis : function (myObject) {
return {
counter : (function (myObject) {
var myVariable = 0;
return function () {
++myVariable;
console.log('index', myVariable); //not incrementing
}
})(myObject)
}
}
}
You need a closure: a function that is declared within a scope of a local variable, and that therefore "remembers" this variable later on.
For example:
TaskHandler = {
doThis : (function () {
var myVariable = -1;
return function () {
++myVariable;
doSomethingWithVariable(myVariable);
};
})(),
// ... rest of TaskHandler's properties ...
}
(where (function () { ... })() is an immediately-invoked function expression).
You can check if the value is undefined, as such:
TaskHandler = {
doThis: function() {
if (typeof this.myVariable === 'undefined') {
this.myVariable = 0;
}
doSomethingWithVariable(this.myVariable);
}
}
You have to put your var somewhere, but it does not need to be in global scope or as a filed of your object.
Considering you are using plain ES5, in a browser, so I do exclude all the bells and whistles of ES6's new features, you can do something like this:
(function () {
var myVariable = 0;
window.taskHandler = {
doThis : function () {
myVariable++;
doSomethingWithVariable(myVariable);
}
}
})()
So, the myVariable is not exposed and your global object is not "polluted".
I have following javascript code
function MyFunc () {
var add = function () {
return "Hello from add";
};
var div = function () {
return "Hello from div";
};
var funcCall = function (obj) {
if (!obj) {
throw new Error("no Objects are passed");
}
return obj.fName();
};
return {
func: function (obj) {
funcCall(obj);
}
};
}
var lol = new MyFunc();
When lol.func({fName: add}); is passed it should invoke the function private function add or when lol.func({fName: div}); is passed it should invoke the private div function. What i have tried does not work. How can i achieve this.
DEMO
In this case it's better to store your inner function in the object so you can easily access this with variable name. So if you define a function "map"
var methods = {
add: add,
div: div
};
you will be able to call it with methods[obj.fName]();.
Full code:
function MyFunc() {
var add = function () {
return "Hello from add";
};
var div = function () {
return "Hello from div";
};
var methods = {
add: add,
div: div
};
var funcCall = function (obj) {
if (!obj) {
throw new Error("no Objects are passed");
}
return methods[obj.fName]();
};
return {
func: function (obj) {
return funcCall(obj);
}
};
}
var lol = new MyFunc();
console.log( lol.func({fName: 'add'}) );
When you pass lol.func({fName: add}) add is resolved in the scope of evaluating this code, not in the scope of MyFunc. You have to either define it in that scope like:
function MyFunc () {
var add = function () {
return "Hello from add";
};
var div = function () {
return "Hello from div";
};
var funcCall = function (obj) {
if (!obj) {
throw new Error("no Objects are passed");
}
return obj.fName();
};
return {
add: add,
div: div,
func: function (obj) {
funcCall(obj);
}
};
}
var lol = new MyFunc();
lol.func({fName: lol.add});
Or use eval.