Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Javascript code block as a parameter for a function

Tags:

javascript

Given this piece of code (simplification of a React component I came by):

const myFn = function(
  {otherFn = () => {console.log('inside myFn declaration'); return 'true'}}
  ){
      console.log('Inside myFn2 ', otherFn());
      foo(otherFn);
      bar(otherFn);
      ...
}

myFn({name:'some name', type: 'some type'});
// output:
// inside myFn declaration
// Inside myFn2  true

I don't understand what is going on there. What's this construct? I'm referring to what is inside 'myFn()'

This construct/code-block is being called no matter what argument (therefore it doesn't behave as a default parameter)

What's more, the purpose of it seems to be 'otherFn' being made available inside the implementation of the function so it can be passed as a callback to other functions.

If the goal was to have otherFn available inside myFn body, it could have been implemented (in a maybe easier way to understand) as:

const myFn = function(){
  otherFn = () => {console.log('inside myFn declaration'); return 'true'}
  console.log('Inside myFn2 ', otherFn());
  foo(otherFn);
  bar(otherFn);
    ...
  }
}
// Output exactly the same as above

There has to be a simple explanation of what this construct is, but I don't seem to be able to connect it with anything I know of JavaScript.

Any hints on what's going on?

EDIT to include some of the answers: Interestingly, if I use this code like:

function myFn({
  name: 'some name',
  type: 'some type',
  otherFn: () => { console.log("other function"); return false; }
}){
  console.log('here');
} 

it does not work :-( using either node or console of chomium In order for it to work, the ':' should be '=' because it is assigning default values.

More EDIT. I've chosen Thomas' answer because although others have hinted me in the right direction (thanks Benjamin, Ainitak and all) I failed to fully 'see' it until I read Thomas' detailed explanation.

Thank you guys you're the best!

like image 513
Jaime Avatar asked May 10 '18 09:05

Jaime


People also ask

Can a JavaScript function have parameters?

A JavaScript function can have any number of parameters. The 3 functions above were called with the same number of arguments as the number of parameters. But you can call a function with fewer arguments than the number of parameters.

How do you pass an array as an argument to a function in JavaScript?

Method 1: Using the apply() method: The apply() method is used to call a function with the given arguments as an array or array-like object. It contains two parameters. The this value provides a call to the function and the arguments array contains the array of arguments to be passed.

Can objects be passed as parameters JavaScript?

In JavaScript, you can use functions as values, just like numbers, strings, and objects. That means you can pass them as arguments, return them from other functions, and set them as properties of objects.

How do you call a function named myFunction in JavaScript?

Define a function named "myFunction", and make it display "Hello World!" in the <p> element. Hint: Use the function keyword to define the function (followed by a name, followed by parentheses). Place the code you want executed by the function, inside curly brackets. Then, call the function.


1 Answers

This combines two features:

default value for an argument:

const fn = (value = 42) => { 
  console.log("value:", value);
}

fn(13);
fn();
.as-console-wrapper{top:0;max-height:100%!important}

wich is basically a shorthand for

const fn = (value) => { 
  if(value === undefined) value = 42;

  console.log("value:", value);
}

And object destructuring as an agument

const fn = ({ foo, bar }) => { 
  console.log(foo, bar);
}

fn({ foo: 10, bar: 100 });
fn({ foo: 13 });
fn(window.location);
.as-console-wrapper{top:0;max-height:100%!important}

basically

const fn = (__arg) => { 
  let foo = __arg.foo;
  let bar = __arg.bar;

  console.log(foo, bar);
}

Just that __arg is just a value that doesn't have an actual name inside your function.


Summary:

const myFn = function({
  otherFn = () => {
      console.log('inside myFn declaration'); 
      return 'true'
    }
  }){
      console.log('Inside myFn2 ', otherFn());
      foo(otherFn);
      bar(otherFn);
      ...
}

is just the combination of these two features: Object destructuring of an argument with a default value for that argument that just happens to be a function.

Works like this:

const myFn = function(__arg){
  let otherFn = __arg.otherFn;
  if(otherFn === undefined){
    otherFn = () => {
      console.log('inside myFn declaration'); 
      return 'true' //why 'true' as a string?
    }
  }

  console.log('Inside myFn2 ', otherFn());
  foo(otherFn);
  bar(otherFn);
  ...
}

What's more, the purpose of it seems to be 'otherFn' being made available inside the implementation of the function so it can be passed as a callback to other functions.

If the goal was to have otherFn available inside myFn body, it could have been implemented (in a maybe easier way to understand)

The purpose of this construct is to provide you (who uses/calls the function) with the ability to inject this method into the function as some property of the configuration object and provide a fallback/default, if you don't pass this config property.

Imo the only uncommon thing about this construct is that the type of this property is function and that they have chosen to inline the function that serves as the default value.

like image 114
Thomas Avatar answered Sep 29 '22 11:09

Thomas