Im trying to call functions with same signature.
Example: There are two functions with same name:
<script>
var obj1,obj2,obj3,obj4,obj5;
function OpenBox(obj1,obj2){
// code
}
function OpenBox(obj1,obj2,obj3,obj4,obj5){
// code
}
</script>
When I calling function on click event of link
<a id='hlnk1' href='#' onclick='OpenBox(this,\"abhishek\"); return false;'> Open Box </a>
When I click on the above link it is calling function OpenBox(obj1,obj2,obj3,obj4,obj5){}
It should be call function OpenBox(obj1,obj2){} Instead.
What's going wrong in functions?
mattn has the correct idea. Because javascript has no typing those functions are equivalent. What you could do is something like this:
function OpenBox_impl1(obj1,obj2){
// code
}
function OpenBox_impl2(obj1,obj2,obj3,obj4,obj5){
// code
}
function OpenBox(obj1, obj2, obj3, obj4, obj5) {
if(arguments.length == 2)
return OpenBox_impl1(obj1, obj2);
else
return OpenBox_impl2(obj1,obj2,obj3,obj4,obj5);
}
javascript can't define duplicate function in same scope. check arguments.length are 2 or 5.
You cannot overload functions in JavaScript. Instead, the most recently defined version of the function will be used, which is why in your case the version with 5 parameters is called (the final 3 are just undefined).
There are several ways around this, one if which is shown in Mikola's answer. An alternative is to pass in an object, and then check the contents of that object in the function (see this question):
function foo(a, b, opts) {
}
foo(1, 2, {"method":"add"});
foo(3, 4, {"test":"equals", "bar":"tree"});
Another option is to check arguments.length:
function foo(a, b) {
if(arguments.length > 2) {
var arg3 = arguments[3];
//etc...
}
}
in the polymorphism you can use a different signature method ,in javascript we can simulate polymorphism checking the type of the function parameter and execute certain task.
var input = document.getElementById('data');
polymorphism(input);
polymorphism('Hello word 2');
polymorphism('hello word 3', 5);
function polymorphism(arg,arg1){
var string = null;
var sqr = 0;
if(typeof arg === 'string'){
string = 'arg type String: \n'+arg;
}else if (arg.tagName && arg.tagName === 'INPUT'){
string = 'arg type Input: \n'+arg.value;
}
if(arg1 && typeof arg1 === 'number'){
sqr = arg1*arg1;
alert(string + ' and sqr = '+sqr);
}else {
alert(string);
}
}
Check this example in JSFIDDLE
#abshik ,
There is nothing like that which is similar to c# or java. Javasccript behaves this way
function Test(arg1 ,arg2 , arg3, arg4)
{
}
when you are calling this function you can call in the following ways
Test(arg1);
Test(arg1,arg2);
Test(arg1,arg2,arg3);
Test(arg1,arg2,arg3,arg4);
But sequence matters , so you can the function in the above ways.
The issue is that you are trying to overload a function but that is not supported by Javascript. I think your best option is to use Polymorphism instead. View this article for more details: http://www.cyberminds.co.uk/blog/articles/polymorphism-in-javascript.aspx
Once a function is defined in ecmascript, that name is locked. However, you can pass any number of parameters to that function so you do the rest of the work on the inside.
function foo(arg1, arg2) {
// any code that is needed regardless of param count
if(arg2 !== undefined) {
// run function with both arguments
console.log(arguments);
} else if(arg1 !== undefined) {
// run function with one argument
} else {
// run function with no arguments
}
}
foo(1);
foo(1,2);
foo(1,2,3);
Interesting note: you can pass in extra parameters that aren't in the function declaration. Do a console.log of arguments and you'll see everything in there. arguments is an object which can be accessed like / typecasted to an array.
Related
I want to create a function like below.
This is the expect function of jest. I want to create this function in Javascript.
Is this do-able??
let type = 'apple'
expect(type).toBe('apple')
//pass a string to "expect" function and it checks with 'toBe' function if the string is similar
Update: I know we can do something like below but i am unable to do something like this "expect().toBe()"
var Expect = Expect || {};
Expect.String = function() {
var toBe = "tobe";
var toBe = function() {
console.log("toBE function");
};
return {
toBe: toBe
}
}()
Expect.String.toBe(); // this will log "toBe function"
This is just a small example of what you are likely going for. You want expect to be a function that returns an object where one of the keys, toBe, is a function. In this example, I just have it returning true or false depending on whether the actual equals expected value.
function expect(actual) {
return {
toBe: function(expected) {
return actual === expected;
}
}
}
console.log(
expect("foo").toBe("foo")
);
console.log(
expect("foo").toBe("bar")
);
It is recommended to not reinvent the wheel, but since you are already there, here is what I recommend in a nutshell:
The function expect() takes a first thing(a.k.a actual) and returns an object that contains yet another function: toBe()
The function toBe() takes second thing (a.k.a expected) as a parameter, uses some form of comparator against the first thing, and returns a boolean
For simplicity, the comparator can be ==
Based on these three elements, Your re-invented expect() function can take the alike of the following shape:
function expect(actual){
return {
toBe: function(expected){
return actual == expected;
}
}
}
The actual implementation is a little more complicated than this answer ~ For the real-world implementation of expect in Jest is at this GitHub address
The "matchers" (as they call alikes of toBe(), toEqual(), etc) can also be found in this source code
How do I pass a function as a parameter without the function executing in the "parent" function or using eval()? (Since I've read that it's insecure.)
I have this:
addContact(entityId, refreshContactList());
It works, but the problem is that refreshContactList fires when the function is called, rather than when it's used in the function.
I could get around it using eval(), but it's not the best practice, according to what I've read. How can I pass a function as a parameter in JavaScript?
You just need to remove the parenthesis:
addContact(entityId, refreshContactList);
This then passes the function without executing it first.
Here is an example:
function addContact(id, refreshCallback) {
refreshCallback();
// You can also pass arguments if you need to
// refreshCallback(id);
}
function refreshContactList() {
alert('Hello World');
}
addContact(1, refreshContactList);
If you want to pass a function, just reference it by name without the parentheses:
function foo(x) {
alert(x);
}
function bar(func) {
func("Hello World!");
}
//alerts "Hello World!"
bar(foo);
But sometimes you might want to pass a function with arguments included, but not have it called until the callback is invoked. To do this, when calling it, just wrap it in an anonymous function, like this:
function foo(x) {
alert(x);
}
function bar(func) {
func();
}
//alerts "Hello World!" (from within bar AFTER being passed)
bar(function(){ foo("Hello World!") });
If you prefer, you could also use the apply function and have a third parameter that is an array of the arguments, like such:
function eat(food1, food2) {
alert("I like to eat " + food1 + " and " + food2 );
}
function myFunc(callback, args) {
//do stuff
//...
//execute callback when finished
callback.apply(this, args);
}
//alerts "I like to eat pickles and peanut butter"
myFunc(eat, ["pickles", "peanut butter"]);
Example 1:
funct("z", function (x) { return x; });
function funct(a, foo){
foo(a) // this will return a
}
Example 2:
function foodemo(value){
return 'hello '+value;
}
function funct(a, foo){
alert(foo(a));
}
//call funct
funct('world!',foodemo); //=> 'hello world!'
look at this
To pass the function as parameter, simply remove the brackets!
function ToBeCalled(){
alert("I was called");
}
function iNeedParameter( paramFunc) {
//it is a good idea to check if the parameter is actually not null
//and that it is a function
if (paramFunc && (typeof paramFunc == "function")) {
paramFunc();
}
}
//this calls iNeedParameter and sends the other function to it
iNeedParameter(ToBeCalled);
The idea behind this is that a function is quite similar to a variable. Instead of writing
function ToBeCalled() { /* something */ }
you might as well write
var ToBeCalledVariable = function () { /* something */ }
There are minor differences between the two, but anyway - both of them are valid ways to define a function.
Now, if you define a function and explicitly assign it to a variable, it seems quite logical, that you can pass it as parameter to another function, and you don't need brackets:
anotherFunction(ToBeCalledVariable);
There is a phrase amongst JavaScript programmers: "Eval is Evil" so try to avoid it at all costs!
In addition to Steve Fenton's answer, you can also pass functions directly.
function addContact(entity, refreshFn) {
refreshFn();
}
function callAddContact() {
addContact("entity", function() { DoThis(); });
}
I chopped all my hair off with that issue. I couldn't make the examples above working, so I ended like :
function foo(blabla){
var func = new Function(blabla);
func();
}
// to call it, I just pass the js function I wanted as a string in the new one...
foo("alert('test')");
And that's working like a charm ... for what I needed at least. Hope it might help some.
I suggest to put the parameters in an array, and then split them up using the .apply() function. So now we can easily pass a function with lots of parameters and execute it in a simple way.
function addContact(parameters, refreshCallback) {
refreshCallback.apply(this, parameters);
}
function refreshContactList(int, int, string) {
alert(int + int);
console.log(string);
}
addContact([1,2,"str"], refreshContactList); //parameters should be putted in an array
You can also use eval() to do the same thing.
//A function to call
function needToBeCalled(p1, p2)
{
alert(p1+"="+p2);
}
//A function where needToBeCalled passed as an argument with necessary params
//Here params is comma separated string
function callAnotherFunction(aFunction, params)
{
eval(aFunction + "("+params+")");
}
//A function Call
callAnotherFunction("needToBeCalled", "10,20");
That's it. I was also looking for this solution and tried solutions provided in other answers but finally got it work from above example.
Here it's another approach :
function a(first,second)
{
return (second)(first);
}
a('Hello',function(e){alert(e+ ' world!');}); //=> Hello world
In fact, seems like a bit complicated, is not.
get method as a parameter:
function JS_method(_callBack) {
_callBack("called");
}
You can give as a parameter method:
JS_method(function (d) {
//Finally this will work.
alert(d)
});
The other answers do an excellent job describing what's going on, but one important "gotcha" is to make sure that whatever you pass through is indeed a reference to a function.
For instance, if you pass through a string instead of a function you'll get an error:
function function1(my_function_parameter){
my_function_parameter();
}
function function2(){
alert('Hello world');
}
function1(function2); //This will work
function1("function2"); //This breaks!
See JsFiddle
Some time when you need to deal with event handler so need to pass event too as an argument , most of the modern library like react, angular might need this.
I need to override OnSubmit function(function from third party library) with some custom validation on reactjs and I passed the function and event both like below
ORIGINALLY
<button className="img-submit" type="button" onClick=
{onSubmit}>Upload Image</button>
MADE A NEW FUNCTION upload and called passed onSubmit and event as arguments
<button className="img-submit" type="button" onClick={this.upload.bind(this,event,onSubmit)}>Upload Image</button>
upload(event,fn){
//custom codes are done here
fn(event);
}
By using ES6:
const invoke = (callback) => {
callback()
}
invoke(()=>{
console.log("Hello World");
})
If you can pass your whole function as string, this code may help you.
convertToFunc( "runThis('Micheal')" )
function convertToFunc( str) {
new Function( str )()
}
function runThis( name ){
console.log("Hello", name) // prints Hello Micheal
}
You can use a JSON as well to store and send JS functions.
Check the following:
var myJSON =
{
"myFunc1" : function (){
alert("a");
},
"myFunc2" : function (functionParameter){
functionParameter();
}
}
function main(){
myJSON.myFunc2(myJSON.myFunc1);
}
This will print 'a'.
The following has the same effect with the above:
var myFunc1 = function (){
alert('a');
}
var myFunc2 = function (functionParameter){
functionParameter();
}
function main(){
myFunc2(myFunc1);
}
Which is also has the same effect with the following:
function myFunc1(){
alert('a');
}
function myFunc2 (functionParameter){
functionParameter();
}
function main(){
myFunc2(myFunc1);
}
And a object paradigm using Class as object prototype:
function Class(){
this.myFunc1 = function(msg){
alert(msg);
}
this.myFunc2 = function(callBackParameter){
callBackParameter('message');
}
}
function main(){
var myClass = new Class();
myClass.myFunc2(myClass.myFunc1);
}
I am a beginner to JS world, and I have a question.
when I was studying .forEach() javascript function, I noticed that it takes 2 parameters, the first is a function and the second is the value of This obj and the normal usage like this:
function logArrayElements(element, index, array) {
console.log('a[' + index + '] = ' + element);
}
// Notice that index 2 is skipped since there is no item at
// that position in the array.
[2, 5, , 9].forEach(logArrayElements);
but I noticed also that it can be called also like this:
example num 2 :
[2, 5, , 9].forEach(function(){
console.log(arguments);
});
if .forEach() function takes a callback function as a parameter, how the second example is correct because it takes a function definition not a reference to a function which will be called,
I mean why it accepts a function definition in the second example although it takes a defined function name?
I mean also that forEach need a reference to a function only, so when it loops on each element, it will just add () to the function reference so the function will be called
function definition in javascript returns pointer to that function. You can also go through syntax like
let myFunction = function() { ... } // define function and save it into variable
myFunction() // call the defined function
So passing function by name and passing function definition is same thing
In the second example, the parameter is an anonymous function as compared to first where you defined the function first and used it's reference to pass to .forEach(). So, both are essentially same. You can also write second example like
[2, 5, , 9].forEach(function(element, index, array){
//do something with element
});
If you take a look at Polyfill what it does is it first check if the type of passed callback is a function and if it isn't then it throws an error, otherwise it uses call() to invoke that function so it doesn't matter if its anonymous function or function declaration.
It also checks if number of passed arguments is > 1 or if there is one more parameter after callback and you can access that parameter with this in your callback.
function invoke(callback) {
if (typeof callback !== 'function') {
throw new TypeError(callback + ' is not a function');
}
if (arguments.length > 1) var Obj = arguments[1];
var value = 1;
callback.call(Obj, value);
}
invoke(function(e) {
console.log(this)
console.log(1 + e)
}, {foo: 'bar'})
var another = function(e) {
console.log(10 + e)
}
invoke(another);
to reach to the correct answer you have to:
read the correct marked answer comments (the last comment), then read the answer Nenad Vracar as both of them covered my missed approaches, thanks for both of them.
Is there a way to tell the difference between this
((a=true)=>{return a})(true)
And this?
((a=true)=>{return a})()
They both return true - how can I tell whether that true is coming from the default value of the argument, or from the value passed in to that parameter?
Is it possible from outside the function?
Is it possible from inside the function?
Is there a way to tell the difference between these two?
No. Arrow function doesn't support argument object, so there is no way to check this.
But, if you are using non-arrow functions, you can get arguments number from inside the function. For example:
(function(a=true){return arguments.length;})(); // 0
(function(a=true){return arguments.length;})(true); // 1
You can easily figure out how to extend this to multiple arguments.
You cannot tell the difference in your specific examples, and there is no way to tell from outside the function definitely. The only exposed info is what you explicitly expose with your return value, which is just the boolean.
From inside the function, you can tell the difference if you rewrite your logic. You could change your function from
((a=true)=>{
return a;
})(true)
to
((...args)=>{
const a = args[0] === undefined ? true : args[0];
if (args.length > 0) console.log("passed arg");
else console.log("passed no arg");
return a;
})(true)
Note that you cannot combine this with default value syntax, so if you'd have to rewrite it to use rest syntax.
Alternatively, you could use a normal function instead of an arrow, and use arguments, however that is also a potentially difficult change if your real-world case relies on the arrow-function's lexical this. e.g.
(function(a = true)=>{
if (arguments.length > 0) console.log("passed arg");
else console.log("passed no arg");
return a;
})(true)
Although not ideal in every way, one solution might be:
(a=undefined) => {
let is_default = false;
if (a === undefined) {
is_default = true;
a = true;
}
return a
}
If you really want to use arrow functions, you can achieve a robust (if convoluted) result using Symbol and a wrapping IIFE
var fn = ((def) =>
(a = def) => {
if(a === def) {
console.log('defaulted');
a = true;
}
console.log('a is', a);
}
)(Symbol());
both fn() and fn(true) will result in a is true - however, fn() will also output defaulted and then set a = true - though this last step I guess doesn't have to done, depends on what the real content of the real function you really want to "detect" this in
Or, a better way as pointed out by #Bergi (I keep forgetting about the block scope in ES6+ :D )
var fn;
{
const def = Symbol();
fn = (a=def) => {
if(a === def) {
console.log('defaulted');
a = true;
}
console.log('a is', a);
};
}
How do I pass a function as a parameter without the function executing in the "parent" function or using eval()? (Since I've read that it's insecure.)
I have this:
addContact(entityId, refreshContactList());
It works, but the problem is that refreshContactList fires when the function is called, rather than when it's used in the function.
I could get around it using eval(), but it's not the best practice, according to what I've read. How can I pass a function as a parameter in JavaScript?
You just need to remove the parenthesis:
addContact(entityId, refreshContactList);
This then passes the function without executing it first.
Here is an example:
function addContact(id, refreshCallback) {
refreshCallback();
// You can also pass arguments if you need to
// refreshCallback(id);
}
function refreshContactList() {
alert('Hello World');
}
addContact(1, refreshContactList);
If you want to pass a function, just reference it by name without the parentheses:
function foo(x) {
alert(x);
}
function bar(func) {
func("Hello World!");
}
//alerts "Hello World!"
bar(foo);
But sometimes you might want to pass a function with arguments included, but not have it called until the callback is invoked. To do this, when calling it, just wrap it in an anonymous function, like this:
function foo(x) {
alert(x);
}
function bar(func) {
func();
}
//alerts "Hello World!" (from within bar AFTER being passed)
bar(function(){ foo("Hello World!") });
If you prefer, you could also use the apply function and have a third parameter that is an array of the arguments, like such:
function eat(food1, food2) {
alert("I like to eat " + food1 + " and " + food2 );
}
function myFunc(callback, args) {
//do stuff
//...
//execute callback when finished
callback.apply(this, args);
}
//alerts "I like to eat pickles and peanut butter"
myFunc(eat, ["pickles", "peanut butter"]);
Example 1:
funct("z", function (x) { return x; });
function funct(a, foo){
foo(a) // this will return a
}
Example 2:
function foodemo(value){
return 'hello '+value;
}
function funct(a, foo){
alert(foo(a));
}
//call funct
funct('world!',foodemo); //=> 'hello world!'
look at this
To pass the function as parameter, simply remove the brackets!
function ToBeCalled(){
alert("I was called");
}
function iNeedParameter( paramFunc) {
//it is a good idea to check if the parameter is actually not null
//and that it is a function
if (paramFunc && (typeof paramFunc == "function")) {
paramFunc();
}
}
//this calls iNeedParameter and sends the other function to it
iNeedParameter(ToBeCalled);
The idea behind this is that a function is quite similar to a variable. Instead of writing
function ToBeCalled() { /* something */ }
you might as well write
var ToBeCalledVariable = function () { /* something */ }
There are minor differences between the two, but anyway - both of them are valid ways to define a function.
Now, if you define a function and explicitly assign it to a variable, it seems quite logical, that you can pass it as parameter to another function, and you don't need brackets:
anotherFunction(ToBeCalledVariable);
There is a phrase amongst JavaScript programmers: "Eval is Evil" so try to avoid it at all costs!
In addition to Steve Fenton's answer, you can also pass functions directly.
function addContact(entity, refreshFn) {
refreshFn();
}
function callAddContact() {
addContact("entity", function() { DoThis(); });
}
I chopped all my hair off with that issue. I couldn't make the examples above working, so I ended like :
function foo(blabla){
var func = new Function(blabla);
func();
}
// to call it, I just pass the js function I wanted as a string in the new one...
foo("alert('test')");
And that's working like a charm ... for what I needed at least. Hope it might help some.
I suggest to put the parameters in an array, and then split them up using the .apply() function. So now we can easily pass a function with lots of parameters and execute it in a simple way.
function addContact(parameters, refreshCallback) {
refreshCallback.apply(this, parameters);
}
function refreshContactList(int, int, string) {
alert(int + int);
console.log(string);
}
addContact([1,2,"str"], refreshContactList); //parameters should be putted in an array
You can also use eval() to do the same thing.
//A function to call
function needToBeCalled(p1, p2)
{
alert(p1+"="+p2);
}
//A function where needToBeCalled passed as an argument with necessary params
//Here params is comma separated string
function callAnotherFunction(aFunction, params)
{
eval(aFunction + "("+params+")");
}
//A function Call
callAnotherFunction("needToBeCalled", "10,20");
That's it. I was also looking for this solution and tried solutions provided in other answers but finally got it work from above example.
Here it's another approach :
function a(first,second)
{
return (second)(first);
}
a('Hello',function(e){alert(e+ ' world!');}); //=> Hello world
In fact, seems like a bit complicated, is not.
get method as a parameter:
function JS_method(_callBack) {
_callBack("called");
}
You can give as a parameter method:
JS_method(function (d) {
//Finally this will work.
alert(d)
});
The other answers do an excellent job describing what's going on, but one important "gotcha" is to make sure that whatever you pass through is indeed a reference to a function.
For instance, if you pass through a string instead of a function you'll get an error:
function function1(my_function_parameter){
my_function_parameter();
}
function function2(){
alert('Hello world');
}
function1(function2); //This will work
function1("function2"); //This breaks!
See JsFiddle
Some time when you need to deal with event handler so need to pass event too as an argument , most of the modern library like react, angular might need this.
I need to override OnSubmit function(function from third party library) with some custom validation on reactjs and I passed the function and event both like below
ORIGINALLY
<button className="img-submit" type="button" onClick=
{onSubmit}>Upload Image</button>
MADE A NEW FUNCTION upload and called passed onSubmit and event as arguments
<button className="img-submit" type="button" onClick={this.upload.bind(this,event,onSubmit)}>Upload Image</button>
upload(event,fn){
//custom codes are done here
fn(event);
}
By using ES6:
const invoke = (callback) => {
callback()
}
invoke(()=>{
console.log("Hello World");
})
If you can pass your whole function as string, this code may help you.
convertToFunc( "runThis('Micheal')" )
function convertToFunc( str) {
new Function( str )()
}
function runThis( name ){
console.log("Hello", name) // prints Hello Micheal
}
You can use a JSON as well to store and send JS functions.
Check the following:
var myJSON =
{
"myFunc1" : function (){
alert("a");
},
"myFunc2" : function (functionParameter){
functionParameter();
}
}
function main(){
myJSON.myFunc2(myJSON.myFunc1);
}
This will print 'a'.
The following has the same effect with the above:
var myFunc1 = function (){
alert('a');
}
var myFunc2 = function (functionParameter){
functionParameter();
}
function main(){
myFunc2(myFunc1);
}
Which is also has the same effect with the following:
function myFunc1(){
alert('a');
}
function myFunc2 (functionParameter){
functionParameter();
}
function main(){
myFunc2(myFunc1);
}
And a object paradigm using Class as object prototype:
function Class(){
this.myFunc1 = function(msg){
alert(msg);
}
this.myFunc2 = function(callBackParameter){
callBackParameter('message');
}
}
function main(){
var myClass = new Class();
myClass.myFunc2(myClass.myFunc1);
}