JS - 03.09 - Function Object

Functions as Objects

In JavaScript, functions are first-class objects. This means that they are objects themselves, and you can treat them like any other object: assign them properties, pass them around as arguments, or even add methods to them.

The name Property

The name property of a function refers to its name. This is especially useful for debugging or logging purposes.

function sayHi() {
    alert("Hi");
}

alert(sayHi.name);  // Outputs: sayHi

Method Names in Objects Even methods defined inside objects have the name property, which reflects the name of the method.

let user = {
    sayHi() {
        alert("Hi");
    },
    sayBye: function() {
        alert("Bye");
    }
};

alert(user.sayHi.name);  // Outputs: sayHi
alert(user.sayBye.name); // Outputs: sayBye

Anonymous Functions and the name Property

If a function is anonymous (i.e., it doesn’t have a name), the name property will be an empty string.

let arr = [function() {}];
alert(arr[0].name);  // Outputs: <empty string>

This is because anonymous functions do not have a name by default. But interestingly, in some cases, modern JavaScript engines will try to infer the function name based on the variable or context it’s assigned to.


The length Property

The length property of a function returns the number of parameters that the function expects (i.e., the number of parameters in its declaration). This does not include the rest parameters or any other arguments passed dynamically.

Examples:

function f1(a) {}
function f2(a, b) {}
function f3(a, b, ...more) {}

alert(f1.length);  // 1
alert(f2.length);  // 2
alert(f3.length);  // 2 (Rest parameters aren't counted)

Here, f1 has one parameter, so f1.length is 1. f3 uses a rest parameter (...more), but it still counts only the non-rest parameters (a and b), so f3.length is 2.

https://javascript.info/function-object

https://javascript.info/new-function

Creating Functions Dynamically with new Function

You can create a function dynamically from a string using the new Function() constructor. This is the only way to create functions from code that is not defined directly in your source code.

let func = new Function([arg1, arg2, ..., argN], functionBody);
let sum = new Function('a', 'b', 'return a + b');
alert(sum(1, 2));  // 3
  • 'a' and 'b' are the arguments.
  • 'return a + b' is the function body.

Function Without Arguments:

let sayHi = new Function('alert("Hello")');
sayHi();  // Outputs: Hello

Here, sayHi is a function that displays an alert with the string "Hello" when called.

Dynamic Functions from Strings (e.g., from a Server):

You can also create functions dynamically from strings received from a server, which makes this feature quite powerful but also potentially dangerous (see below for security concerns).

let str = 'alert("This is dynamic!")';  // Code string from the server
let func = new Function(str);
func();  // Outputs: This is dynamic!

This is useful when you want to evaluate or execute code that might not be hard-coded into your script.


Security Concerns with new Function

While the new Function() constructor can be powerful, it introduces security risks because it allows execution of dynamically generated code (often received from external sources, like a server). This can open the door to code injection attacks if the string is not carefully validated or sanitized.

If you create a function from user input without sanitizing it, it could execute malicious code.

let userInput = 'alert("Hacked!")';  // Simulating user input
let func = new Function(userInput);  // Dangerous!
func();  // This will run the malicious alert!

To avoid this, never use new Function() with unsanitized input from untrusted sources.


Closure with new Function

Functions created using new Function() behave slightly differently from regular functions in terms of closures. When a function is created using the new Function constructor, its lexical environment is set to the global context (window in browsers, global in Node.js), not the local context where the function is created.

Example of new Function and Closure:

function getFunc() {
    let value = "test";

    // Creating a function with `new Function` won't have access to the local `value`
    let func = new Function('alert(value)');

    return func;
}

getFunc();  // Error: value is not defined

Here, value is not accessible in the function because new Function() creates the function in the global scope and doesn’t capture the local variables (value in this case) as a closure would.


Summary:

  1. Functions are objects in JavaScript, meaning they can have properties like name and length, and can be treated as first-class objects.
  2. The name property gives the name of the function, and length tells how many parameters the function expects (excluding rest parameters).
  3. The new Function() constructor allows you to create functions from strings, enabling dynamic function generation, but this can introduce security risks if not used carefully.
  4. Closures created with new Function() have a different lexical environment and don’t capture variables from the local scope like normal functions do.