Currently I am working on Learning React and Redux. I have found a boilerplate, and I am working on looking through all of the example code. My problem is I don't completely understand what a lot of this ES6 syntax means.
What I have learned so far is that hello = () => "Hello"; would be equivalent to:
hello = function hello() {
return "Hello";
};
Then changing the above to hello = name => "Hello " + name; would convert it to:
hello = function hello(name) {
return "Hello " + name;
};
That all makes perfect sense, basically it is just shortening it down so you don't have to write the function and its return statement. Yet, I have come across some syntax that I cannot rap my head around. It is as follows:
const mapActionCreators = {
increment: () => increment(1),
doubleAsync
}
The above code is converted to:
var mapActionCreators = {
increment: function (_increment) {
function increment() {
return _increment.apply(this, arguments);
}
increment.toString = function () {
return _increment.toString();
};
return increment;
}(function () {
return increment(1);
}),
doubleAsync: doubleAsync
};
I understand that () => increment(1) in this case is being turned in to:
(function () {
return increment(1);
}),
Overall I guess my question is, how does increment: get converted in to:
increment: function (_increment) {
function increment() {
return _increment.apply(this, arguments);
}
increment.toString = function () {
return _increment.toString();
};
return increment;
}
What is the meaning of the code?
Arrow functions capture the value of this from the scope they are created in.
apply lets you call a function and explicitly the value of this in it.
The rest of the code is just feeding the correct this to the function.
(And toString is making sure that the right function gets stringified if you try to stringify the generated function).
Related
I have a question regarding curry function..
I know that if I have this simple curry function:
const greeting = (greet) => {
return (name) => {
return `${greet} ${name}`;
};
};
I can call greeting('Hello')('John') and it will return Hello John.
Is there a way to make it flexible say between 1 parameter and 2 parameters, ex: with
the above greeting function, is there a way for me to call greeting('Hello') and greeting('Hello')('John') and it will return Hello and Hello John respectively?
I know that I can do it with greeting('Hello')() and greeting('Hello')('John') but I was just trying to avoid breaking changes because I already have a greeting method and want to extend it using curry function, so I want it to also accept greeting('Hello') without the extra () at the end...
thanks
I can think of only one option that works by coercing the curried function into a string. This won't change the return value but it will allow you to get the result you want depending on context.
const greeting = greet => Object.defineProperties(
name => `${greet} ${name}`, // curried
{
toString: {
value: () => greet,
},
valueOf: {
value: () => greet
}
}
)
console.log(typeof greeting("Hello")) // function, not string
console.log(`${greeting("Hello")}`) // note the string context
console.log(`${greeting("Hello")("World")}`)
If you need the return value to actually toggle between a function and a string however, the answer is no.
In order for greeting("Hello")("John") to return a string, greeting("Hello") must return a function.
There is no way to tell within greeting() how the curried function is going to be called so you cannot detect whether or not to return a function or a string.
Think of it this way, greeting("Hello")("John") is just a short version of...
const fn = greeting("Hello")
// later or maybe never...
fn("John")
You simply don't know how, when or even if that curried function will be called.
Is there a way? Sure. But why? because won't that be "un-currying" it? And you will have to modify the function of-course.
You can always do something like this just get the output your asked for:
const greeting = (greet) => {
const split = greet.split(" ");
if(split.length > 1)
return `${split[0]} ${split[1]}`;
else return (name) => {
return `${greet} ${name}`;
};
};
If you use a helper function for currying, you can get a similar behavior automatically. For example, take the implementation at javascript.info/currying-partials
function curry(func) {
return function curried(...args) {
if (args.length >= func.length) {
return func.apply(this, args);
} else {
return function(...args2) {
return curried.apply(this, args.concat(args2));
}
}
};
}
You can define
const greeting = curry((greet, name) => `${greet} ${name}`)
and call
greeting("Hello", "John")
or
greeting("Hello")("John")
So I have a function like
func()
{
const curVal = this.curVal;
const callAgain = () => { func(); };
Axios.get('somecontroller/someaction')
.then(response =>
{
const newVal = response.data.curVal;
if(curVal === newVal)
setTimeout(callAgain, 500);
else
// ....
})
.catch(response =>
{
// ...
});
}
and my browser is complaining about the line
const callAgain = () => { func(); };
saying that func is undefined. Any idea why? How can I fix?
You cannot define a function the way you posted.
However, you can for example use the function keyword to define your function:
function func() {
...
}
func(); // it works!
Edit:
According to your comment, this is a object method declaration. In order to make this work, you first need to make sure your browser supports this particular ES2015 feature or if not, you transpile it to valid ES5.
Then you should be able to access the function using this.func():
const callAgain = () => { this.func(); };
In case you are using func() e.g. as a callback for a DOM event, you also have to make sure that this is bound correctly in func, for example by explicitly binding it in the constructor:
constructor() {
...
this.func = this.func.bind(this);
}
Define the function using either of the following:
function func(){ ... }
Or...
var func = function(){ ... }
When you define it like this:
func() { ... }
JavaScript thinks you're trying to execute an existing function called func, and then run the block of code { ... }
Because I'm using a prototype that has functions calling other functions in the same prototype I have to refer to that method using this
The Problem this Created:
But because of that, I have to preserve a context to use this that has me forming very ugly .bind(this) walls.
Here is a simplified example I made for laughs.
Killmyself.prototype.fireLeMissles = function () {
return new Promise(function(resolve,reject) {
this.anotherFunction(param).then(function(result) {
someList.forEach(function(item) {
this.fireLeMissles().then(function(anotherResult){
promiseList.push(anotherResult)
})
},this);
Promise.all(promiseList).then(function(promiseItem){
childPlacesIds.forEach(function(childPlaceId) {
//Do Other Stuff
},this);
});
resolve(result);
}.bind(this).catch(function(err){
console.log("Yea, life sucks sometimes.")
}));
}.bind(this));
}
Killmyself.prototype.another = function(){
//Other stuff
}
You can see because of calls to functions in the same prototype such as this.anotherFunction(... and this.fireLeMissles(... I had to do deep preservation of context,which now (in my much larger version of this) is making this code hard to work with.
Question:
Is this a "man up and get use to the harder aspects of JavaScript" thing - or do you seasoned developers see simple ways that deep binding like this could have been avoided?
If you are using ES6, you can benefit from arrow functions, which preserve the context.
var counter = function () {
this.count = 0;
setInterval( () => { // arrow function
console.log(this.count++); // context is preserved
}, 1000)
}
var counter = new counter();
So, your code would become something like:
Killmyself.prototype.fireLeMissles = function() {
return new Promise((resolve, reject) => {
this.anotherFunction(param).then(result => {
someList.forEach(item => {
this.fireLeMissles().then(anotherResult => {
promiseList.push(anotherResult)
});
});
Promise.all(promiseList).then(promiseItem => {
childPlacesIds.forEach(childPlaceId => {
//Do Other Stuff
});
});
resolve(result);
}).catch(err => {
console.log("Yea, life sucks sometimes.")
});
});
}
For ES5, you can just either use .bind just like the way you did or you can assign this to something else in the function with the desired context, then use that variable inside the inner functions.
Killmyself.prototype.fireLeMissles = function() {
var self = this; /// use `self` instead of `this` from now on.
return new Promise(function(resolve, reject) {
self.anotherFunction(param).then(function(result) {
someList.forEach(function(item) {
self.fireLeMissles().then(function(anotherResult) {
promiseList.push(anotherResult)
})
});
Promise.all(promiseList).then(function(promiseItem) {
childPlacesIds.forEach(function(childPlaceId) {
//Do Other Stuff
});
});
resolve(result);
}).catch(function(err) {
console.log("Yea, life sucks sometimes.")
});
});
}
for starters I do not understand you you need a new Promise.. here, like #loganfsmyth said, I would simply use arrow functions and reduce the complexity:
Killmyself.prototype.fireLeMissles = function (param) {
return this.anotherFunction(param)
.then(someList => {
var promiseList = someList.map( item => this.fireLeMissles(item));
return Promise.all(promiseList);
}).then(childPlacesIds => {
childPlacesIds.forEach(childPlacesId = {
// .... do something;
});
// return something.
}).catch(err => console.log("Yea, life sucks sometimes."));
}
P. S: I am not sure where this param, someList, childPlacesIds is coming from, and assumed that you are initializing that promiseList as empty array.
Mido's answer is good, I just wanted to provide an alternative take on it which I think would be useful to know - using promises for the proxies they are:
Killmyself.prototype.fireLeMissles = function () {
let fn = this.anotherFunction(param);
let others = fn.then(_ => someList.map(this.fireLeMissles, this));
let othersP = Promise.all(others);
othersP.then(/* do OtherStuff */);
return othersP; // or whatever its then returned
}
Of course, this gets even easier with a library like bluebird.
Im new to JS and trying to learn. The spec requires the following:
Write a function that takes another function* as an argument and creates a version of the function that can only be called one time. Repeated calls to the modified function will have no effect, returning the value from the original call. How could you do this without using a closure? Is it even possible? How could you do this with a closure? *Note: This original input function should not have any parameters.
This is what I have:
var divide = function () {
var x = 2;
var y = 6;
return y/x;
}
var mainFunc = function (func) {
return func(){
return y/x + 1;
}
}
var output = mainFunc(divide);
console.log(divide());
console.log(output());
console.log(output());
I'm getting an "Unexpected token{" error at "return func(){" I don't quite understand what i'm doing wrong? Per the spec, I am passing divide() to mainFunc() and setting it to a reference variable output. I then call the divide() and output() multiple times to test if the closure works and that modified function only happens once. What am I missing or not understanding?
Thanks for the help.
Here you go:
function runonce(func) {
return (function(func) {
var ran = false;
var retval;
return function() {
if (!ran) {
ran = true;
retval = func();
}
return retval;
}
})(func);
}
function realfunction() {
console.log('really running');
return 5;
}
var realfunctionrunner = runonce(realfunction);
realfunctionrunner();
realfunctionrunner();
realfunctionrunner();
Study the code, the whole trick is a "self contained library" which result is returned from the runonce function
Creating the closure is easy but using it is confusing for me. Here is my closure. Once I have it I need to be able to call operations on it like doWork, calculateThis, doAnimation, etc. but there doesn't seem to be a way to access functions inside the closure.
function worker(input) {
return function () {
doWork = function () {
alert("doing work");
};
}
}
function caller() {
var myWorker = worker();
myWorker.doWork(); // this fails
}
*The question you're asking appears subjective and is likely to be closed. - Thanks again stackoverflow
I believe this is what you are asking for:
function worker(input) {
return {
doWork: function () {
alert("doing work");
},
doAnimation: function() {
alert("animating");
}
}
}
You can now call it using your code:
var myWorker = worker();
myWorker.doWork();
myWorker.doAnimation();
Note that your code is not really using closures, but this one does:
function worker(input) {
return {
doWork: function () {
alert("doing work: " + input);
},
doAnimation: function() {
alert("animating: " + input);
}
}
}
var workerA = worker('A');
var workerB = worker('B');
workerA.doWork();
workerB.doAnimation();
Can you see the difference?
You are trying to execute a method work() but in your example you return a function, not an object with a property "work".
Here's what you're probably after:
function worker(input) {
return {
work: function () {
alert("doing work");
};
}
}