Lesson 51: Mastering JavaScript Function Objects & NFE with challenges!

๐ง What is a Function in JavaScript?
In JavaScript, functions are first-class objects. This means:
They can be stored in variables.
They can be passed as arguments to other functions.
They can be returned from functions.
They can have properties and methods, just like any other object.
โ
Functions are "callable objects" with internal [[Call]]
and optional [[Construct]]
behaviors.
๐งช Examples
function greet(name) {
return `Hello, ${name}`;
}
greet.language = 'English';
console.log(greet('Manoj')); // Hello, Manoj
console.log(greet.language); // English (property on function)
๐ Function Properties
name
(Read-only)
Auto-assigned based on declaration or contextual naming.
let f = function custom() {};
console.log(f.name); // "custom"
Even anonymous functions can have a contextual name:
let greet = function() {};
console.log(greet.name); // "greet"
length
Returns the number of formal parameters (excluding rest parameters and defaults).
function f(a, b, ...rest) {}
console.log(f.length); // 2
๐น 2. Fill Any Gaps
๐ฌ Internal Mechanics
Functions have internal slots:
[[Environment]]
: lexical scope[[Code]]
: function body[[ThisMode]]
: controls howthis
is resolved (lexical
,strict
,global
)
๐ชค Common Misconceptions
Not all function expressions have names.
function foo() {}
is a Function Declaration. But:let bar = function foo() {}; // is an Expression
func.name
inside an anonymous function is not always empty โ JS engines often infer it.
โ ๏ธ Behavior in Strict Mode
"use strict";
function f(a, a) {} // โ SyntaxError in strict mode
๐งฑ Function Object vs Closure Variable
function makeCounter() {
function counter() {
return counter.count++;
}
counter.count = 0;
return counter;
}
Here, .count
is attached to the function object, not its closure.
โ Alternative: closure-based encapsulation.
๐ง Named Function Expression (NFE)
NFE enables safe recursion inside assigned functions:
let sayHi = function func(who) {
if (!who) return func("Guest");
console.log(`Hello, ${who}`);
};
Why not just call sayHi()
inside? Because sayHi
could be reassigned or nulled externally. func
is only visible inside the function body.
๐น 3. Challenge Me Deeply
๐ข Basic
Create a function
add
with a.count
property that tracks how many times it was called.Write a function that logs its
name
andlength
.Define a function with rest parameters and show how
length
behaves.
๐ก Intermediate
Write a
memoize(fn)
utility that caches function calls by attaching.cache
to the function.Create a function object with helper functions attached (like
_.isArray
,_.isNumber
).Build a polyfill checker using
globalThis
andFunction.name
to log unsupported functions.
๐ด Advanced
Create a recursive NFE that finds the factorial, and safely works even if reassigned.
Implement a rate-limited function with
.lastCalledTime
as a function property.Emulate private state using closure vs function property โ then compare memory exposure.
Write a meta-function that accepts any function and logs its
.name
and.length
, then calls it.
๐ฏ Bonus Brain-Twister
What will be logged?
let sayHi = function func(who) {
if (!who) return func("Guest");
console.log(`Hello, ${who}`);
};
let welcome = sayHi;
sayHi = null;
welcome();
๐น 4. Interview-Ready Questions
๐ Conceptual
Why are functions considered objects in JavaScript?
What is the purpose of a Named Function Expression?
๐ก Scenario
How would you build a logger that tracks how often a function is used?
When would you use a function property instead of a closure?
๐งฉ Debugging
- Why is this code failing?
let sayHi = function(who) {
if (!who) sayHi("Guest");
};
let welcome = sayHi;
sayHi = null;
welcome(); // โ Error
โ Best Practices
โ Prefer closures for encapsulated state
โ Use
.name
and.length
for debugging tools๐ซ Avoid relying on contextual names for production logic
๐น 5. Real-World Usage
jQuery:
$
is a function object with many attached helpers ($.ajax
,$.extend
)Lodash:
_
is a function with attached methods like_.map
,_.filter
Event systems:
addEventListener(fn)
โ tracking functions via.id
or metadataAnalytics: Function wrappers that log
.name
or timing
๐น 6. Remember Like a Pro
๐ง Mnemonic
F.L.I.P. โ Key Function Properties
F = Function
L =
length
of parametersI = Internal name (NFE)
P = Properties attached (
counter
,id
, etc.)
๐ Cheatsheet
Property | Type | Description |
name | String | Inferred or defined function name |
length | Number | Number of declared parameters (excl. rest) |
Custom | Any | You can add anything: .counter , .meta , etc. |
๐น 7. Apply It in a Fun Way
๐ฏ Mini Project: Function Tracker Utility
Goal: Track function invocations, durations, and arguments.
๐ Steps:
Create a function
track(fn)
that wraps any function.Store call count, duration, and arguments on the wrapper.
Attach
.log()
to view the history.
function track(fn) {
function wrapper(...args) {
wrapper.calls.push(args);
return fn.apply(this, args);
}
wrapper.calls = [];
wrapper.log = () => console.log(wrapper.calls);
return wrapper;
}
const sum = track((a, b) => a + b);
sum(1, 2);
sum(3, 4);
sum.log(); // [[1, 2], [3, 4]]
๐ฎ Extend It Further:
Track average duration
Detect slow functions
Group by
.name
โ Extra Value
๐ Projects That Use This
Lodash, Underscore.js
Express middleware functions often use
.length
for introspectionMocha, Jest sometimes attach properties to test callbacks
โ ๏ธ Common Mistakes
Assuming
length
includes rest parametersUsing external variable names for recursion
Modifying function identity (e.g.,
sayHi = null
) without understanding the consequences
๐งฐ Performance Tips
Avoid bloating function objects with too many properties in tight loops
Use closures for hidden state to avoid external mutation
Prefer named function expressions for self-reference
Subscribe to my newsletter
Read articles from manoj ymk directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
