stringify function with function inside - javascript

is there any way to stringify function which has function inside? I want to stringify bar function.
const foo = (x) => {
return x + x;
};
const bar = (y) => {
return foo(y)
};
bar.toString() returns
function bar(y) {
return foo(y);
}
but I want something like:
const bar = (y) => {
const foo = (x) => {
return x + x;
};
return foo(y);
};
Is it even possible? I want to use bar as follow:
// I don't have control below this line
import bar from 'bar';
`<script>(${bar})(5)</script>`

Is it even possible?
Probably. It is not, at all, simple. To do it, you'd have to use a JavaScript parser like Esprima or the ones in Babel, ESLint, etc. to parse the source code that contains both bar and foo and use the resulting AST to identify the functions that bar calls, convert those functions to source code, convert bar to source code, and insert the functions it calls into the beginning of it. And even then, depending on what those functions call and what things they use that they close over, you may have more work to do.
It's tempting to think "Well, I could just use toString on the functions and then a bit of regular expression to figure out what functions bar calls." But JavaScript source code syntax is far too complex to correctly identify function calls in a function's code with a regex or two. You need a proper parser.
As someone said in the comments (now deleted), this sounds like an X/Y problem — like you're trying to solve some other problem by doing this odd conversion of bar. I would focus on solving that problem a different way instead.

Related

What do the square brackets after ES6 function do?

Recently I was looking for a way to rewrite an ugly switch/case statement and came across this Medium article.
I rewrote my switch/case into an es6 function like this:
const url = category => ({
'itemA': itemAService.getItemCategories(payload),
'itemB': itemBService.getItemCategories(payload),
})[category]
When I call this function with something like const response = url(category); it works, which is great! But then I got to wondering what exactly the [category] means at the end of the function. I thought maybe it was an Immediately Invoked Function, but that didn't seem right either.
The article mentions that it's an object literal, but when I went to the MDN docs I couldn't find anything that explained what this is or what it does, or even any examples that showcase this same thing.
So what does it do?
That shorthand is roughly equivalent to the following traditional function syntax:
function url(category) {
var obj = {
'itemA': itemAService.getItemCategories(payload),
'itemB': itemBService.getItemCategories(payload),
};
return obj[category];
}
It's easier to see what's happening when you create a named variable for the object.
The parentheses are needed around the object in the arrow function because if an arrow function begins with { it's treated as a body containing statements, rather than a value to return.
They could have put [category] immediately after the object literal, rather than after the close parenthesis, that might have been clearer.
It's not "after" the function, it is in the functions body. It could also be written as:
const url = category => {
const obj = {
'itemA': itemAService.getItemCategories(payload),
'itemB': itemBService.getItemCategories(payload),
};
return obj[category];
};
So this is basically just a dynamic property lookup in the object.
What confuses you here are the braces.
Imagine that you have an object expression and you use a property assessor on the variable which points to the object.
obj = {foo: 1, bar: 2}
return obj["foo"]; //returns 1
Now, how would you call a property assessor on an object literal? You need braces around them to complete the shorthand syntax.
return {foo: 1, bar: 2}["foo"]; // WRONG Syntax
return ({foo: 1, bar: 2})["foo"]; // CORRECT syntax
So, your function can be rewritten using the following traditional syntax.
function getUrl(category) {
return ({
'itemA': itemAService.getItemCategories(payload),
'itemB': itemBService.getItemCategories(payload),
})[category]
}

JavaScript challenge

So I have a small JavaScript function that I need to figure out how to code, as a challenge. Basically:
function me() { // imp this function code }
var isSame1 = me("123")("321") === "123 321";
var isSame2 = me("321")("123") === "321 123";
Desired output is we want both isSame vars to be true. So from what I understand thus far, the me() function needs to return a function initially (some form of recursion I'd imagine) and then somehow a string in order to concat the resulting strings (the real example has some string manipulation during the me() function but I don't need help with that part).
I feel like there is a JavaScript feature that I am not seeing clearly here. I am aware that I can return a function as an object and call it, which is a really neat feature, but the string handling/passing to the other function and then returning it in the end is what is confusing me.
Can anyone point me in the right direction for what to look up. Don't want it to be answered completely for me, just want to be given the right research area.
Gerneio
Currying in JavaScript is quite easy. Just return a scoped function from me().
For example, to implement curried addition using a closure, you could write a function like this:
function add (a) {
return b => a + b
}
console.log(add(3)(4))
Or see below for the solution to the challenge.
Spoiler (full implementation):
function me (a) {
return b => `${a} ${b}`
}
console.log(me(123)(321))
console.log(me(321)(123))
Hope this helps you find what you're looking for.

How do I read functional composition in es6/javascript?

Background:
Composition is putting two functions together to form a third function where the output of one function is the input of the other.
No matter how much I look at this I struggle with how to read it. In particular why the compose() return => (a) => captures the 121.2121212 in local scope. Also I struggle with how final fn f(g(a)) would look with all the values/fn present w/o the use of variables.
Question: Does anyone have any techniques or diagrams for quickly reading examples like this; how can I mentally debug and follow the function flow?
Reference:
const compose = (f, g) => (a) => f(g(a)) // Definition
const floorAndToString = compose((val) => val.toString(), Math.floor) // Usage
floorAndToString(121.212121) // '121'
As mentioned by T.J. Crowder, it often helps rewriting arrow functions as regular functions. So the function:
const compose = (f, g) => (a) => f(g(a))
Can be rewritten as:
function compose (f, g) {
return function (a) {
return f(g(a));
}
}
Now it is perhaps more obvious what's going on. So now let's rewrite the other parts:
const floorAndToString = compose((val) => val.toString(), Math.floor)
Can be rewritten as:
function convertToString (val) { return val.toString() };
const floorAndToString = compose(convertToString, Math.floor);
Now it may be more obvious that the compose function will return the function:
// remember that we pass `convertToString` as `f`
// and `Math.floor` as `g`:
function (a) {
return convertToString(Math.floor(a));
}
So it's obvious that the function floorAndToString simply returns the result of convertToString(Math.floor(a)). There is nothing special about compose that captures 121.2121212 because it doesn't. Instead it creates a function where 121.2121212 can be passed as an argument to convertToString(Math.floor(a)).
It might help to look at the Wikipedia article for function composition. But I think your problem is not really related to function composition but to the arrow notation in general.
Maybe it helps to look at a simpler example first:
const addOne = (x) => x + 1
const addN = (n) => (x) => x + n
const addSeven = addN(7)
The last line produces a new function that adds seven to the input (x) => x + 7. You can think of the parameter tuples between the arrows as being filled from left to right when values are provided (and the variables to the right are bound to these values). As long as you don't provide all parameters, you will obtain a new function.
You can also provide all parameters like this:
addN(5)(3) // yields 8
Note that addN can be seen as taking two parameters but in separate bracket pairs. The arrows between the brackets in the definition kind of allow you to omit parameters to the right and obtain a function with fewer parameters with the left ones being already fixed.
Let's look at an alternative definition of compose:
const weirdCompose = (f, g, a) => f(g(a))
It should be clear how it works, but the problem is that you cannot use this to compose two functions without evaluating the result of the composition with the value a right away. By separating the parameters into two groups you can partially apply the function and only provide f and g in a first step.
To understand this better, I suggest you also have a look at the concept of currying

NewBee on NodeJs or PhantomJS: Function names on Javascript

I am just learning NodeJS and/or PhantonJS.
As a programmer with a lot of C experience, I do not like the way NodeJs code is written and find it a bit messy/unreadable. (Sorry if I ruffled any feathers)
In spirit of cleaning up the code, I was trying to do this and found a block.
In C or C++, we should be able to pass a function by name but in NodeJS/PhantomJS it does not seem to work.
Am I doing somthing wrong ?
Can someone explain to me how this is looked at by the Javascript interpreter ?
var page = require('webpage').create();
var printS = function (s) {
console.log(s);
phantom.exit();
}
/* This works */
page.open('http://net.tutsplus.com', function (s) {
console.log(s);
phantom.exit();
});
/* This does not work
page.open('http://net.tutsplus.com', printS(status));
*/
/*But this works
page.open('http://net.tutsplus.com', function (s) { printS(s);} );
*/
page.open('http://net.tutsplus.com', printS(status));
fails because you're not passing the function but rather the result of invoking the function on status. If you want to pass the function, you'd do it this way
page.open('http://net.tutsplus.com', printS);
I thought it might be helpful to have a more extensive explanation. Let's start simple:
In JavaScript, we have values and variables. Variables are containers for values. Almost everywhere where we can use values, we can use variables.
In JavaScript source code, we express values through literals, e.g. the number literal 42. We can directly pass that value to a function:
f(42);
Additionally, instead of passing the value directly, we can pass a variable to the function:
var v = 42;
f(v);
That is, we can substitute values with variables.
Lets consider
var printS = function() { ... };
This clearly is a variable whose value is a function. If we'd directly pass that value to a function (i.e. we pass a function to a function), it would look like:
f(function() { ... }); // similar to f(42)
That's exactly what you have in your first case:
page.open('http://net.tutsplus.com', function (s) {
// ...
});
Since we know that we can replace values with variables, we can just substitute function() { ... } with printS:
var printS = function() { ... }; // similar to var v = 42;
f(printS); // similar to f(v)
So your example would become
page.open('http://net.tutsplus.com', printS);
What is wrong with
page.open('http://net.tutsplus.com', printS(status));
then?
Notice that you added additional characters after printS, namely (status). They don't appear in the your first example where you inlined the function:
page.open('http://net.tutsplus.com', function (s) {
// ...
});
There is no (status) here. Hence these two constructs cannot be not equivalent.
page.open accepts a function value as second argument, but printS(status) doesn't evaluate to the function printS, it calls the function printS and passes the return value to page.open.
Why does
page.open('http://net.tutsplus.com', function (s) { printS(s);} );
work?
Lets remove the content and the argument of the function, and it becomes:
page.open('http://net.tutsplus.com', function () { ... } );
That looks exactly like one of the examples above. function () { ... }, is a function literal, so to speak. It creates a function value. There are no (...) after it which would call the function.
This doesn't work as you hope because page.open wants a function as its second argument... this callback pattern is very common in JavaScript. In your doesn't-work example, printS is being called with status as its argument, and it returns undefined. As undefined is not a function, it doesn't behave as you wish.
In your browser console or the node repl:
> printS = function (s) { console.log(s); };
function (s) { console.log(s); }
> typeof printS('hi');
hi
"undefined"
> typeof function (s) { printS(s); };
"function"
Another thing to know about JavaScript is that its dynamic typing and fairly generous type coercion can result in baffling behavior with no helpful errors to point you towards the root cause of your problem. A debugger or copious use of console.log() is frequently helpful in understanding these sort of problems.

Arbitrary object methods and properties in JavaScript

I'm sure this has definitively been answered before, and I've tried to search for it.. maybe my search terms are wrong...
Basically I have an object myObject, and I have a set of defined properties and methods for it. What I want to do is be able to handle calls/references to properties and methods that I have not defined.
For example, let's say I have this:
var myObject = {
someProperty : 'foobar',
someFunction : function () { /* Do stuff */ }
}
Currently, if someone tries to make a call to myObject.someOtherFunction(), JavaScript yells and screams about it. What I want to do is setup a way to automatically handle that. So for example, instead of JavaScript throwing an error, my object just returns false. Is this possible?
Another way to look at it is this:
var myObject = {
someFunction : function () { /* Do stuff */ }
magicBucket : function () { /* Do stuff */ }
}
If I call myObject.someFunction(), well that is defined and does something. What I want to happen is if I were to for instance call myObject.someOtherFunction(), instead of JavaScript throwing an error, it would call myObject.magicBucket().
The reason is that I have a client that uses a third-party library on their site. They want to discontinue using it, but completely removing it is going to take a lot of time and effort. So as a short-term solution, they wanted to know if I could make a dummy file that basically does nothing. Well, this library uses several objects that has lots of methods. I could go through everything and make dummy objects, but I thought maybe there might be some easy "catch-all" method to do this.
Some have mentioned checking if the method exists first, wrapping it in a condition or try..catch, etc. Well, the point of this is that at this time I can't touch the actual calls to the methods. And since the overall goal is to eventually remove the coding altogether, it's not even applicable.
There's a special property called __noSuchMethod__ which does precisely what you just described. However it's a non-standard property. It only works in Firefox. Here's how you use it:
var o = {
__noSuchMethod__: function (name, args) {
alert(name); // prints the name of the method
alert(args); // prints the array of arguments
}
};
o.abc(1, 2, 3); // OUTPUT: abc 1,2,3
The future however are proxy objects. The following is a short tutorial on proxies: Proxy Tutorial
No, you can't have arbitrary getters in JavaScript. You can test if a function exists before calling it to prevent the error though:
if (myObject.someOtherFunction)
myObject.someOtherFunction();
Or, better, if you don't know that it's necessarily a function:
if (typeof myObject.someOtherFunction == 'function')
myObject.someOtherFunction();
An update on Proxies, here is an infinite array:
$ var squares = new Proxy([], {get:(target,key) => key*key});
$ squares[2]
4
$ Array.isArray(squares)
true
Unfortunately:
$ squares.length
NaN // Want Infinity.
And a dummy object:
$ x = new Proxy({}, {get:(target,key) => console.error("The computer says no", key)})
$ x.laugh
The computer says no laugh
This latter would help the OP make a dummy object, although it would take a bit of black magic to divine what sort of dummy to return.
An up-to date reference: https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Proxy
You could create a wrapper function like so:
function callFunction(fn, args) {
var funct = this[fn];
return (typeof funct == "function")
? funct.apply(this, args)
: false;
}
And call with:
callFunction("blah", [1, 2, 3]);
>>> false
An example:
this.foo = function(a, b) {
console.log(a);
return b;
}
callFunction("foo", [1, 2, 3]);
>>> 1
>>> 2 # return value
With Proxy the following works:
function createPseudoObject() {
return new Proxy(new Function(), { get() { return createPseudoObject() } })
}
Eg. createPseudoObject().foo.bar.toString() does not throw error and returns undefined. By using new Function() as a base for the dummy object I can reference not just any property, but call any function on the dummy object.
Maybe there are some edge cases that are not covered by this, but something like this should work.

Categories