Calling function within a Function - javascript

I have a situation where I generate code from within a Blockly component. The resulting code will have a function that I want to call. According to the Blockly "Generating and Running JavaScript" documentation, I should use eval().
When I look up eval() on MSDN, I get a section that I should "never use eval" and use Function instead.
Here is some example code from what the output of the code could be:
let blocklyResult = `function onExecute() {
console.log('Function has been called!');
}`;
let code = new Function(blocklyResult);
I want to call the onExecute function from within the code variable, but I cannot figure out how I can do that?
What is the best way to accomplish my desired result.

the Function constructor will generate a function with the string code inside. if the string code come in format of function, the function will generate this function, but you also need to call it. So ether (if you can) pass as a string the code to execute (not function) or add execute the function yourself. like this:
var a = `function onExecute(){console.log('Function has been called')}`
var b = new Function(`(${a})()`);
b();

Following Function document link, you should define function just from code lines, not include something like function XXXXX() {}
So, it should be
let blocklyResult = `console.log('Function has been called!')`;
let code = new Function(blocklyResult);
code()

let blocklyResult = `function onExecute() {
console.log('Function has been called!');
}`;
// v1
let code1 = new Function(`${blocklyResult};onExecute();`);
code1();
// v2
let code2 = (new Function(`return ${blocklyResult}`))();
code2();
v1 creates a new function every time it's called
v2 returns the function so it can be called multiple times without recreating the blockly function
v2 is preferable IMO

Related

Function Composition: Augmenting an existing function with additional function in Javascript

I import a library with a function and would like to replace that function with a function that takes the original function as an argument together with an additional function.
The original function might be logThis:
function logThis() {console.log('this'));
I can create a new function which executes logThis and then logs 'that';
function logThisThenThat() {
logThis();
console.log('that');
}
I would like to replace logThis with a new function which executes the original function and thereafter another function? Is this possible with function composition or will I have to create a new function with a different name which is made up of the original function and additional functions.
Something along the lines of:
logThis = compose(logThis, logThat);
You can create a function like this.
function logThis() {
console.log("this");
}
function logThat() {
console.log("that");
}
let compose = (...func) => ()=> {
let functions = func;
functions.forEach((fn) => fn());
}
logThis = compose(logThis, logThat);
logThis();
Adding (...func) as parameters, you can execute 3, 4 any amount of functions you like/need.
Note: Edit the snippet to match the question. The selected answer by #mark-meyer is correct.
You can override the existing function with a new one.
Keep a copy of the original like this...
_logThis = logThis;
...and then make your new version call the original one...
function logThis() {
_logThis();
// your other function call or new code goes here
}
This isn't a particularly good idea though, since that will modify what happens for every single existing call to that method. This needs to be handled with care.
Also, scope is a big factor here. This is a basic example of what you're trying to do.
If you pass logThis() into your compose() function, you will hold a reference to it in the closure, so it will live on when you make a new logThis(). The name isn't really that important so long as you rename in an order that lets you get the reference to the old logThis() before you point the name at a new function. For example, the right side of logThis = compose(logThis, logThat) runs before the name assignment below, so you capture the function reference before reassigning the name:
function logThis() {console.log('this')};
function logThat() {console.log('that')};
let compose = (f1, f2) => () => {
f1()
f2()
}
logThis = compose(logThis, logThat)
logThis()

JS Encapsulation - IIFE vs Regular Function

Learning the JS Module Pattern.
I am trying to figure out the differences between an IIFE and a regular function in this use case. It looks like the ONLY advantage of an IIFE is that my module becomes an object (since the IIFE returns immediately) so I don't need to use the call invocation/param () syntax on my module.
Is there any additional benefit? Consider the following code:
//IIFE
var HelloWorldEncapsulated = (function(){
return {
privateMethodEncapsulated: function () {
console.log('ayy lmao encapsulated');
}
}
})();
HelloWorldEncapsulated.privateMethodEncapsulated();
//Just a function
var HelloWorld= function(){
return {
privateMethod: function () {
console.log('ayy lmao');
}
}
};
HelloWorld().privateMethod();
Again, is there any difference between the two besides using () and not using it? It seems that privateMethod is just as hidden in the non-IIFE function as it is in the IIFE. Code here in case you don't want to type 2 words
The only difference in those is when you're executing your function. In your second example, if you want to call another method (or call privateMethod more than once), you'd have to execute it again (not ideal):
HelloWorld().privateMethod();
HelloWorld().privateMethod(); // Calls HelloWorld a second time, creating a
// whole new object to make the call on (bad idea)
...or remember the result of the first execution an dreuse it:
var hw = HelloWorld();
hw.privateMethod();
hw.privateMethod();
...at which point you're back to your first example.

JavaScript OOP and Reflection - Are there any (non-trivial/ugly hack) ways to call a 'private' method from outside a class itself?

Are there any (non-trivial/ugly hack) ways to call a 'private' method from outside a class/module itself?
Please don't ask why I need this.
Just my personal curiosity and trust in power of doing anything in JS :)
function Module () {
var privateMethod = function () {
alert('1');
};
var publicMethod = function () {
privateMethod();
alert(2);
};
return {
pm: publicMethod
};
}
var m = new Module();
m.pm(); // can i call m.privateMethod() here somehow?
DON'T TRY THIS AT HOME
So you've been warned, now look at this (fiddle; I've replaced all the alerts with console.log() for the greater good):
var methodName = 'privateMethod';
var mSource = Module.toString();
var methodPattern = new RegExp(methodName + '\\s*=\\s*function[^]*?\\{([^]+?)\\};');
var privateMethodSource = mSource.match(methodPattern);
var privateMethodRebuilt = new Function([], privateMethodSource[1]);
privateMethodRebuilt();
It's one possible way to do this with HUGE number of restrictions. First, this particular snippet doesn't even try to parse the arguments, assuming that the method in question doesn't need any. Second, you won't be able to access the other private variables defined within the Module (as the code rebuilds only the particular function, not the environment).
Surely, you can take it further - and rebuild the Module itself, making the target method public (for example, by adding the private function into the exposed methods' list). The question is, WHY on Earth do you even think about needing such thing as using the private method outside the module?

Passing argument to function I don't want to execute immediately

Sorry if my question seems naive (a bit of a newbie here), but I seem not to be able to get a simple answer to my question.
In JavaScript I try something like this
window.onload = init; *// ok, this assigns to the window load event a function that doesn't execute straight away*
// now I define my init()function
function init(){
// say...
alert('Noise!');
/* but here is my dillema...
Next say I want to assign to an button.onclick event a function that only executes when I click the button.
But (!here it is...!) I want to pass arguments to this function from here without causing to execute because it (obviously) has brackets.
Something like: */
var button = document.getElementById('button');
var promptInput = prompt("Name?");
button.onclick = printName(promtInput); // I only want to print name on button click
}
function printName(name){
alert(name);
}
So... OK, I know the example is stupid. Simply moving all prompt gathering inside printName() function and assign to button.onclick a bracketless printName function will solve the problem. I know. But, still. Is there a way to pass args to functions you don't want to execute immediately? Or it really is a rule (or 'by definition') you only use functions that await execution when you don't plan to pass args via it?
Or how do you best to this thing otherwise?
Thanks a lot!
Ty
button.onclick = function() {
printName(promptInput);
};
You can use Function.prototype.bind():
The bind() method creates a new function that, when called, has its
this keyword set to the provided value, with a given sequence of
arguments preceding any provided when the new function is called.
For example:
button.onclick = printName.bind(null, promtInput);
You could put the data that you would normally pass as an argument into some other holding location. You can either put it in a hidden HTML element, or you can use the sessionStorage API to keep it. So your code would look like this:
var button = document.getElementById('button');
var promptInput = prompt("Name?");
sessionStorage.setItem('MyName', promptInput);
button.onclick = printName; // I only want to print name on button click
}
function printName(){
alert(sessionStorage.getItem('MyName');
}

IIFE raising error

I'm new to JavaScript programming.I wrote an IIFE that will help me improve my understand. My intention is to define a $ function that when called will call itself as a constructor. When the code is run, it generates an error 'Too much recursion'. I don't know what the problem is.
(function() {
//check the global host object
var root = this;
var inside = "inside";
var $ = function () {
return new $(); //this line generates an error 'Too much recursion.'
}
$.check = function(obj) {
console.log(inside);
}
//add the $ to global object
root.$ = $;
}).call(this);
var ins = $();
console.log(ins);
var $ = function () {
return new $(); //this line generates an error 'Too much recursion.'
}
This function is repeatedly calling itself, which is why you see the Too much recursion. error. You aren't distinguishing between a regular function call and a new call.
My intention is to define a $ function that when called will call itself as a constructor.
The simplest way is to explicitly check this:
var $ = function $() {
if(!(this instanceof $)) return new $();
// ... from this point on, behave as if called via new
}
this line generates an error 'Too much recursion.'
Right. You have a function assigned to the $ symbol which calls the function assigned to the $ symbol. So each call (whether direct or via new) will run the code in that function, which makes another call to it, and so on until you exceed the engine's willingness to recurse. To avoid that, have $ do something else.
It's because you have created an infinite loop. By using parenthesis when returning your new var instance you are recursively calling that function with no parameters. I'm not sure what you are trying to accomplish, but you might want to have $ create a new object "{}" instead and then you can extend methods off of that reference. Look into singleton patterns, that will allow you to create a new instance of something.
*edit, and just to be clear your problem doesn't have anything to do with it being an IIFE, you would encounter this same error anywhere you tried to call a new function on itself in this manner.

Categories

Resources