DEV Community

Ayako yk
Ayako yk

Posted on

Understanding Function.length, Function.name, Polymorphism, and NFE in JavaScript

In JavaScript, functions are one of the fundamental concepts, and I've discussed them in the past blogs. As we know, a function is like a black box: we provide input and get an expected result without needing to understand its internal structure. Given the same input, a function will always produce the same output.

JavaScript has eight data types: string, number, bigint, boolean, undefined, null, symbol, and object. Functions are indeed part of the object type, specifically as Function objects. As such, they inherit properties defined on Function.prototype.

Today, I'll cover the following:

  1. Function.name
  2. Function.length
  3. Polymorphism
  4. Named Function Expression (NFE)

Function.name

The name data property of a Function instance indicates the function's name as specified when it was created, or it may be either anonymous or '' (an empty string) for functions created anonymously.

These examples are from MDN:

function doSomething() {}
doSomething.name; // "doSomething"
Enter fullscreen mode Exit fullscreen mode

Read-only:

function someFunction() {}

someFunction.name = "otherFunction";
console.log(someFunction.name); // someFunction
Enter fullscreen mode Exit fullscreen mode
new Function().name; // "anonymous"
Enter fullscreen mode Exit fullscreen mode
const someFunction = function someFunctionName() {};
someFunction.name; // "someFunctionName"
Enter fullscreen mode Exit fullscreen mode
(function () {}).name; // ""
(() => {}).name; // ""
Enter fullscreen mode Exit fullscreen mode

The name property is read-only and is primarily used for debugging and error messages.

MDN

Function.length

Specifies the number of arguments expected by the function.

Let's learn using the modified examples based on MDN:

function.length returns the number of arguments as a number:

function fn() {}
console.log(fn.length); // 0

function fn(a) {}
console.log(fn.length); // 1

function fn(a, b) {}
console.log(fn.length); // 2
Enter fullscreen mode Exit fullscreen mode

A rest parameter is not counted:

function fn(...args) {}
console.log(fn.length); // 0

function fn(a, b, ...args) {}
console.log(fn.length); // 2
Enter fullscreen mode Exit fullscreen mode

The .length property only counts the parameters before the first default value.

function fn(a, b = 1, c) {}
console.log(fn.length); // 1
Enter fullscreen mode Exit fullscreen mode

Each destructuring pattern is considered one parameter:

function fn({ a, b }, [c, d]) {}
console.log(fn.length); // 2

// { a, b } + [c, d] = 2
Enter fullscreen mode Exit fullscreen mode

MDN

The Modern JavaScript Tutorial provides an example that may seem a little complicated:

function ask(question, ...handlers) { 
    let isYes = confirm(question);

    for(let handler of handlers) { 
        if (handler.length == 0) { 
            if (isYes) handler(); 
        } else { 
            handler(isYes); 
        } 
    } 
} 

// for positive answer, both handlers are called 
// for negative answer, only the second one 
ask("Question?", () => alert('You said yes'), result => alert(result));
Enter fullscreen mode Exit fullscreen mode

This ask function takes a question argument and an unspecified number of handler functions. The handlers can either take zero arguments or one argument. The handler.length property is used in the if condition to determine which handler to call.

This is an example of polymorphism.

Polymorphism

Polymorphism in JavaScript is the ability of a function, method, or object to take multiple forms, allowing the same method name to be used for different implementations depending on the object or class.

There are two types: Method Overriding and Method Overloading.
In the ask function, Method Overloading is used.

Method Overloading (simulated): A function behaves differently based on the number or type of its arguments.
Geeks for Geeks

In the ask function, the same function name (handler) is used for different implementations depending on the number of arguments, which is determined by the .length property.

Named Function Expression (NFE)

Named Function Expression, or NFE, is a term for Function Expressions that have a name.
The Modern JavaScript Tutorial

When we assign a function to a variable, we can skip naming the function. We can even use an arrow function.

const example = function () {};
const example = () => {};
Enter fullscreen mode Exit fullscreen mode

When we add a name to a function, it is called a Named Function Expression.

const example = function exampleFn () {};
Enter fullscreen mode Exit fullscreen mode

Use case of NFE:
According to The Modern JavaScript Tutorial,

  1. It allows the function to reference itself internally.
  2. It is not visible outside of the function.
let sayHi = function(who) { 
    if (who) { 
        alert(`Hello, ${who}`); 
    } else {     
        sayHi("Guest"); // Error: sayHi is not a function 
    } 
}; 
let welcome = sayHi; 
sayHi = null; 
welcome(); // Error, the nested sayHi call doesn't work any more!
Enter fullscreen mode Exit fullscreen mode

As I mentioned in a previous blog, JavaScript uses a lexical environment, so it tries to find a reference in the outer environment. However, when sayHi is called, the variable has been changed.

The following code works because it always references func:

let sayHi = function func(who) { 
    if (who) { 
        alert(`Hello, ${who}`); 
    } else {     
        func("Guest"); // Now all fine 
    } 
}; 

let welcome = sayHi; 
sayHi = null; 
welcome(); // Hello, Guest (nested call works)
Enter fullscreen mode Exit fullscreen mode

Although Function.length and Function.name may not be frequently used in our code, understanding them deeply will enhance our skills as developers.

Top comments (0)