How to "append" an action to a function? - javascript

I wanted to create a function that I can add actions to later. I tried this:
Function.prototype.appendAction = function(action) {
let _ogFn = this
return function(...args) {
_ogFn(...args)
action()
}
}
function a() {
console.log("foo")
}
a()
a = a.appendAction(() => console.log("bar"))
a()
This does work, but how can I make it change the function automatically? I want to make it work like this:
a()
a.appendAction(() => console.log("bar")) //note it doesn't have the "a = "
a() //changed function

Depending on your scenario you could create a function decorator. This would mean defining a function (for example fnMod) that accepts a function fn and returns a decorated version that executes some before and after hooks.
const a = fnMod(() => {
console.log("foo");
});
a();
a.appendAction(() => console.log("bar"));
a();
const john = {
name: "John Doe",
age: 42,
greet: fnMod(function () {
console.log(`I'm ${this.name}.`); // <- uses `this` so use a normal function
})
}
john.greet.prependAction((name) => {
console.log(`Hi ${name}!`); // <- does not use `this` so both a normal function
}); // or arrow function will work fine
john.greet.appendAction(function () {
console.log(`I'm ${this.age} years old.`);
});
john.greet("Jane");
function fnMod(fn) {
const before = [];
const after = [];
function hookable(...args) {
before.forEach(fn => fn.apply(this, args));
const result = fn.apply(this, args);
after.forEach(fn => fn.apply(this, args));
return result;
};
hookable.prependAction = (fn) => {
before.unshift(fn);
}
hookable.appendAction = (fn) => {
after.push(fn);
}
return hookable;
}
You might want to tweak it to your liking. Currently both this and all arguments passed to the decorated function are forwarded to all hooks, which might or might not be desirable.

If you just want to call it immediately:
Function.prototype.appendAction = function(action) {
let _ogFn = this
return (function(...args) {
_ogFn(...args)
action()
})()
}
function a() {
console.log("foo")
}
a.appendAction(() => console.log("bar"))
That is the immediately invoked function expression (IIFE) pattern

For your purposes you could use eval:
First, grab the user input however you are handling it and parse it as a string.
Then use eval like so:
let userInput = 'console.log("hello world")';
const callUserFunction = (action) => {
eval(`function fn(){${action}}`);
fn();
}
callUserFunction(userInput);
Be aware that allowing a user to write or JS is a security risk, which can open doors to all kinds of attacks, so in most scenarios, I would discourage doing so

Related

How to convert an iife old ways function to an arrow function in a single line

how would you convert:
(function(age) {return `your ${age}`;
})(10);
to an arrow function? I tried but doesnt work:
(const years = (age) => `your ${age}`)(10);
Why does not work and if it is because of const?
And then another example, if I make:
const marco= { name: 'marco ccc',
say hi: function () {
return 'something';
}
}
how would I convert sayHi into an arrow function?
I do this often when creating async closures so I can use await inside a non-async function body. It looks like this:
(async (arg1,arg2) => {
console.log(arg1,arg2); // logs a,b
})('a','b');
It saves me from creating a const and then calling it, like this:
const outerFunc = () => {
// ... some code
const innerFunc = async () => {
// I can use await in here
};
innerFunc();
}
and instead I do this:
const outerFunc = () => {
// ... some code
(async () => {
// I can use await in here
})();
}
To juse create the closure, leave off the async part
((...args) => console.log(...args))('a','b');
EDIT: If you look closely at the above, you'll see it actually shortens to
(console.log)('a','b')
Expressions get assigned to variables. Arrow functions are generally composed of 2 parts: the variable it's assigned to, and the body, eg:
const foo = () => { ... }
// ^ variable
^^^^ function body
Initialization of variables can only be done as a statement, on a standalone line; the const can't be inside parentheses. You just need to separate out the variable the return value is being assigned to from (the function body and the call of the function):
const years = ((age) => `your ${age}`)(10);
// ^^^^^^^^^^^^^^^^^^^^^^
// this is the function body
// that needs to be invoked immediately
// ^^ with the (10)
// ^^^^^ with the result assigned to `years`
console.log(years);
In an object, just replace function() with () => (and note that say hi isn't a valid object property in an object literal - either surround it in quotes, or use a single word instead):
const marco = {
name: 'marco ccc',
sayHi: () => {
return 'something';
}
};
console.log(marco.sayHi());
So basically I wanted to convert these two functions (old version):
(function(age) {return `your ${age}`;
})(10);
and
const marco= { name: 'marco ccc',
say hi: function () {
return 'something';
}
}
console.log(marco.sayHi());
Which converted are respectively:
((age) => your age is ${age})(10);
and
const marco= { name: 'marco ccc', sayHi: () => {} }
But in addition, I was trying to understand the benefit of IIFE, for instance:
const years = ((age) => your ${age})(10);
is a shorter version than something like:
const years = (age) => your ${age};
const whatever = years(10);
console.log(whatever);

ES6 Default value parameter for callback [duplicate]

This question already has answers here:
Set a default parameter value for a JavaScript function
(29 answers)
Closed 6 years ago.
I have several functions with optional callback:
let myFunc = (callback) => {
callback = callback || (() => {});
// do something...
callback();
}
What is the best way to write the callback default parameter?
None of the following solutions satisfy me much:
1 If callback defined:
if (typeof callback === 'function') {
callback();
}
Not compact at all!
2 Utility function:
let safeFunc = (callback) => {
return callback || (() => {});
};
let myFunc = (callback) => {
// do something...
safeFunc(callback)();
}
but the problem is that in between this has changed, and it matters in my case.
3 Using call
let myFunc = (callback) => {
// do something...
safeFunc(callback).call(this);
}
Not very user friendly.
4 Creating ID function
const ID = () => {};
let myFunc = (callback=ID) => {
// do something...
callback();
}
Has external dependency, not very functionnal, though probably the best choice.
Calling directly Function() constructor looks meaningful:
let myFunc = (callback = Function()) => {
// do something...
callback();
}
Calling Function() returns a noop function:
let noopFunc = Function()
noopFunc() // => undefined
Here is another option.
5 Just an if check..
if (callback) callback();
If you want to prevent calling the callback twice, another utility function here I've called callIt, it also handles passing arguments, and if this is important also to prevent using bind, just pass this..
function callIt(that, fn) {
if (fn) fn.apply(that, Array.prototype.slice.call(arguments,2));
}
//Test Object
function Test() {
this.test = 'Test';
}
Test.prototype.calltest = function (callback) {
callIt(this, callback, 1, 2, 3);
}
var t = new Test();
t.calltest(
function (a,b,c) {
console.log('this.test = ', this.test);
console.log('args = ', a, b, c);
}
);
// ES6 way:(default parameters)
function(callback=()=>{}) {
if(typeof callback === 'function') {
callback();
}
}

How to call recursively a function stored in a variable in Javascript

How can I achieve that in Javascript?
exports.functions = {
my_func: function (a) {
my_func(a);
}
}
A function expression can have an optional name after the function keyword. The scope of this name is just the function body, and allows it to be called recursively:
exports.function = {
my_func: function this_func(a) {
this_func(a);
}
}
You can also use its full name:
exports.function = {
my_func: function(a) {
exports.function.my_func(a);
}
}
This is not quite ok as a standard, but you can easily achieve this like:
var foo = function(a) {
foo(a);
}
exports.functions = {my_func: foo};
Your code does not work because in this case the hoisting is not done ok(well it's done ok) but not for what you need.

Implementing a 'once' function in JavaScript

I have this spec from Jasmine.js which tests a once function. I'm not sure how to implement such a function though.
/* Functions that decorate other functions. These functions return a version of the function
with some changed behavior. */
// Given a function, return a new function will only run once, no matter how many times it's called
describe("once", function() {
it("should only increment num one time", function() {
var num = 0;
var increment = once(function() {
num++;
});
increment();
increment();
expect(num).toEqual(1);
});
});
I don't quite understand what should I do here. I know I should make a function once(myFunction) {} but other than that, I am stuck. I figure out this has something to do with closures, still can't my head around it.
If you prefer not to use UnderscoreJS, you can implement a simpler "once" function yourself like this:
var once = function (func) {
var result;
return function () {
if (func) {
result = func.apply(this, arguments);
func = null;
}
return result;
}
};
When you pass your function as the argument to this once function (as the parameter as 'func'), it returns a function that can only be called once.
It accomplishes this feat, in short, by creating a results variable and assigning that variable the results of calling your function with its supplied arguments--but only the first time it is run. Otherwise, when the function is invoked subsequent times, it will never enter your if statement (because the func variable was set to null in the first invocation) and the value referenced by the results variable (set during the first invocation and accessed via closure) will be returned.
Copied from the UnderscoreJS source:
_.once = function(func) {
var ran = false, memo;
return function() {
if (ran) return memo;
ran = true;
memo = func.apply(this, arguments);
func = null;
return memo;
};
};
http://underscorejs.org/docs/underscore.html
Very, very minimal
const once = fn => (...args) => {
if (!fn) return;
fn(...args);
fn = null;
};
(Old school version)
function once(fn) {
return function() {
if (!fn) return;
fn.apply(null, arguments);
fn = null;
}
}

Javascript call nested function

I have the following piece of code:
function initValidation()
{
// irrelevant code here
function validate(_block){
// code here
}
}
Is there any way I can call the validate() function outside the initValidation() function? I've tried calling validate() but I think it's only visible inside the parent function.
function initValidation()
{
// irrelevant code here
function validate(_block){
console.log( "test", _block );
}
initValidation.validate = validate;
}
initValidation();
initValidation.validate( "hello" );
//test hello
Hope that you are looking for something like this
function initValidation()
{
// irrelevant code here
this.validate = function(_block){
// code here
}
}
var fCall = new initValidation()
fCall.validate(param);
This will work.
Hope this addresses your problem.
You can call validate from within initValidation. Like this.
function initValidation()
{
// irrelevant code here
function validate(_block){
// code here
}
return validate(someVar);
}
validate is not visible to anything outside of initValidation because of its scope.
Edit: Here's my suggestion of a solution.
(function() {
function validate(_block){
// code here
}
function initValidation()
{
// irrelevant code here
return validate(someVar);
}
function otherFunctions() {
// ...
}
// initValidation = function
}());
// initValidation = undefined
All of your functions will be hidden to anything outside the function wrapper but can all see each other.
This invocation will return function statement, which is function validate.
So you can invoke directly after the first invocation.
function initValidation() {
// irrelevant code here
return function validate(_block) {
// code here
}
}
initValidation()();
I know this is an old post but if you wish to create a set of instances that you wish to work with that reuse the code you could do something like this:
"use strict";
// this is derived from several posts here on SO and ultimately John Resig
function makeClassStrict() {
var isInternal, instance;
var constructor = function(args) {
if (this instanceof constructor) {
if (typeof this.init == "function") {
this.init.apply(this, isInternal ? args : arguments);
}
} else {
isInternal = true;
instance = new constructor(arguments);
isInternal = false;
return instance;
}
};
return constructor;
}
var MyClass = makeClassStrict();// create "class"
MyClass.prototype.init = function(employeeName, isWorking) {
var defaultName = 'notbob';
this.name = employeeName ? employeeName : defaultName;
this.working = !!isWorking;
this.internalValidate = function() {
return {
"check": this.working,
"who": this.name
};
};
};
MyClass.prototype.getName = function() {
return this.name
};
MyClass.prototype.protoValidate = function() {
return {
"check": this.working,
"who": this.name
};
};
var instanceBob = MyClass("Bob", true);// create instance
var instanceFred = MyClass("Fred", false);// create instance
var mything = instanceFred.internalValidate();// call instance function
console.log(mything.check + ":" + mything.who);
var myBobthing = instanceBob.protoValidate();
console.log(myBobthing.check + ":" + myBobthing.who);
I know this thread's been here for quite some time but I thought I'd also leave my 0.02$ on how to call inner functions from outside their scope (might benefit somebody).
Note that in any place, a better design decision should be taken into consideration rather than some hackish workaround which will bite you back later.
How about using function expressions instead of function statements and making use of the global scope.
var innerFn;
function outerFn() {
innerFn = function(number) {
return number ** 2;
}
}
outerFn();
console.log(innerFn(5));
// if there's more complex code around and you could write this defensively
if (typeof innerFn !== 'undefined') {
console.log(`we are squaring the number 5 and the result is: ${innerFn(5)}`);
} else {
console.log('function is undefined');
}
Or, you can make use of closures:
function outer() {
// initialize some parameters, do a bunch of stuff
let x = 5, y = 10;
function inner() {
// keeps references alive to all arguments and parameters in all scopes it references
return `The arithmetic mean of the 2 numbers is: ${(x + y) / 2}`;
}
return inner;
}
innerFn = outer(); // get a reference to the inner function which you can call from outside
console.log(innerFn());
Create a variable outside the parent function, then in the parent function store your required function in the variable.
Var Store;
Function blah() {
Function needed() {
#
}
Store = needed;
}
As a minor variation of Esailija's answer, I did this:
function createTree(somearg) {
function validate(_block) {
console.log( "test", _block );
}
if (somearg==="validate") { return validate; } // for addNodes
// normal invocation code here
validate(somearg);
}
function addNodes() {
const validate = createTree("validate");
//...
validate( "hello" );
}
createTree("create");
addNodes();
//validate("illegal");
so validate() is now perfectly shared between createTree() and addNodes(), and perfectly invisible to the outside world.
Should work.
function initValudation() {
validate();
function validate() {
}
}
Function definition:
function initValidation() {
// code here
function validate(_block){
// code here
console.log(_block);
}
return validate;
}
Call it as below:
initValidation()("hello");
function initValidation()
{
function validate(_block){
console.log(_block)
// code here
}
// you have to call nested function
validate("Its Work")
}
// call initValidation function
initValidation()

Categories