Translation: the dodgers author: Yash Agrawa: the original blog.logrocket.com/defining-fu…

In general, a function is a sequence of instructions or a “subroutine” that can be called by code inside or outside the function. In essence, a function “encapsulates” a specific task. Functions are a fundamental module in JavaScript, and really understanding them can help you understand some of JavaScript’s quirks.

Functions in JavaScript

It’s important to note that functions are an important class of objects in JavaScript, which means that functions in JavaScript can be handled just like any other object, and can be referred to or passed into functions as arguments just like any other variable.

Functions even have properties and methods, just like any other JavaScript object. The key difference between functions and other objects is that functions can be called.

Each Function in JavaScript is a Function object, you can go to the console and try the following script:

function typeCheck() {};
typeCheck instanceof Function // Logs True
Copy the code

Function objects have built-in methods and properties such as apply, Call, bind, isGenerator, etc. Other objects do not.

There are several ways to define a function in JavaScript, each of which affects the final behavior of the function. Let’s take a look at each one.

Function declaration

This is the most common way to define a function. The function declaration includes the keyword function, followed by a function name, followed by a required pair of parentheses with a list of optional arguments.

function sum(param1, param2) {
  return param1 + param2;
}
Copy the code

There are two things to note about defining functions this way:

  • A variable containing the function object is created under the current scope, and the variable’s identifier is the name of the function, in this casesum.
  • Variables are promoted to the top-level domain of the current scope. You can view more here to better understand ascension, take a look at an example:
console.log(notYetDeclared()); // Logs 'Here! '

function notYetDeclared() {
  return 'Here';
}
Copy the code

We can call this function before notYetDeclared is defined.

Functional expression

Function expressions are syntactically similar to function declarations, except that function expressions do not require function names.

let sum = function(param1, param2) {
  return param1 + param2;
};
Copy the code

A function expression is part of a statement. In the above example, the function expression is part of the assignment of the sum variable. Unlike a function declaration, the function expression is not promoted.

console.log(notYetDeclared); // Logs 'undefined'

let notYetDeclared = function() {

  return 'Here';
}
Copy the code

One interesting use scenario for function expressions is the ability to create IIFE or call function expressions immediately. Many times we want to define a function and call it immediately, but not anywhere else.

Of course, you can also do this using function declarations, but to make the code more readable and prevent other programs from accidentally accessing it, you can use IIFE. Look at this code:

function callImmediately(foo) {
  console.log(foo);
}

callImmediately('foo'); // Logs 'foo'
Copy the code

The above code creates the callImediately function, which takes the argument foo, prints it to the console, and then calls it immediately. The same result can be achieved by doing the following:

(function(foo) { console.log(foo); }) ('foo'); // Logs 'foo'
Copy the code

The key difference between the two is that in the first example the function declaration pollutes the global namespace, and the named function callImmediately can still be called anywhere long after it has been used. But IIFE is anonymous, so it can’t be called later.

Arrow function

Arrow functions are new to ES6 and are syntactically compact versions of function expressions. Arrow functions are defined by using a pair of parentheses containing a list of arguments, followed by a double arrow =>, followed by function statements wrapped in curly braces {}.

let sum = (param1, param2) => {
  return param1 + param2;
};
Copy the code

Since one of the main motivations behind the arrow function is its compact syntax, if the arrow function has only return statements, you can remove the curly braces and return keyword, as follows:

let sum = (param1, param2) => param1 + param2;
Copy the code

Similarly, if there is only one argument, the braces can also be removed:

let double = param1 => param1 * 2;
Copy the code

Note the form of this function definition:

  • Arrow functions don’t have their ownthis, it uses closed lexical scope and can be found inhereRead more aboutthisThe content of the
let foo = {
    id: 10,
    logIdArrow: () => { console.log(this.id) },
    logIdExpression: function() {
      console.log(this.id);
    }
  }
  
  foo.logIdArrow(); // Logs 'undefined'
  foo.logIdExpression(); // Logs '10'
Copy the code

In the above example, an arrow function and a function expression are defined in foo, and both call this to record foo.id.

  • Arrow function doesn’t have anyprototypeProperties.
let foo = () => {};
console.log(foo.prototype); // Logs 'undefined'
Copy the code
  • argumentsObject is not available within the arrow functionhereRead more aboutargumentsObject contents

The Function constructor

As mentioned earlier, every Function in JavaScript is a Function object, so to define a Function, you can call the constructor of the Function object directly.

let sum = new Function('param1'.'param2'.'return param1 + param2');
Copy the code

Parameters are comma-separated strings ‘param1’, ‘param2’, ‘param3’… , ‘paramN’ is passed in, and the function body is passed in as the last argument.

This definition Function from a performance into consideration, the way is not so efficient Function declarations or Function expression, use the Function constructor defined Function in each time the constructor is invoked, the constructor will be parsed once, because the Function body of the string need to need to parse every time, don’t like any other way, You just need to parse the rest of the code.

One use for defining functions in this way is to access a global object from a Node or window object in a browser. These functions are often created in global scope and do not need to be accessed in the current scope.

The Generator function

The Generator functions are new to ES6. Generator functions are a special type of function in the sense that unlike traditional functions, Generator functions generate multiple values on a per-request basis and suspend their execution between those requests.

function* idMaker() {
  let index = 0;
  while(true)
    yield index++;
}

let gen = idMaker();

console.log(gen.next().value); // Logs 0
console.log(gen.next().value); // Logs 1
console.log(gen.next().value); // Logs 2
Copy the code

The function* and yield keywords are unique to generator functions. Generator functions define Generator functions by adding an * to the end of the function, which allows us to use yield to generate multiple values on the request in the Generator body. You can see more details here.

conclusion

Which definition type you choose depends on the situation and what you want to implement. Here are a few points to consider:

  • If you want to take advantage of function promotion, use function declarations, for example, with only abstract flow at the top and function implementation details at the bottom for clarity.
  • The arrow function also works with short callback functions, and more importantly is closed when using this.
  • Avoid usingFunctionConstructor to define functions, and if the pesky syntax isn’t enough to keep you away from it, you need to know that it’s very slow, parsed every time it’s called.