Why can't functions expose their inner declarations and act like a class?

This is not a great technical question, but a little one that arised out of my curiosity.
It doesn't particularly concern JS but I guess you guys will tolerate that😅
(The follow isn't valid JS syntax! sorry!!)
It looks like this:

exposed function Greet(name) {
	let fullName;
	for(let i = 0; i <= 500; i++)
		console.log(i)
	// some other statements
	function sayHi() {
		alert( "Hi " + name )
	}
	function sayHello() {
		alert( "Hello " + name )
	}
	function sayGoodBye() {
		alert( "Good bye " + name )
	}
	let #nickname = "Adios"
	function #makeFullName() {
		fullName = #nickname + " " + name
	}
}

Or a function like:

function Greet(name) {
	let fullName;
	for(let i = 0; i <= 500; i++)
		console.log(i)
	// some other statements
	function sayHi() {
		alert( "Hi " + name )
	}
	function sayHello() {
		alert( "Hello " + name )
	}
	function sayGoodBye() {
		alert( "Good bye " + name )
	}
	let nickname = "Adios"
	function makeFullName() {
		fullName = nickname + " " + name
	}
	return export { fullName, sayHi, sayHello, sayGoodBye }
}

greet1 = new Greet("Myself")
greet1.sayHi()

greet2 = new Greet("Myself")
greet2.sayHello()

greet3 = new Greet("Myself")
greet3.sayGoodBye()

greet3.#nickname // Error

Why isn't this sort of functions used in programming languages?

I very well know that JS can do:

function Circle(x, y, r) {
    this.x = x
    this.y = y
    this.r = r
    
    this.draw = () => //Draw it
}
let c = new Circle(100, 100, 10)

Thanks for any help👍

If functions worked like that, how would you prevent exposing function-internal helper functions? You'd end up needing syntax to keep things private, which means the default behavior would be for every function's implementation details to be part of its API - which means that renaming or removing one of these helper functions would be a breaking change to consumers.

1 Like

Your second example is very similar to something that can already be done:

Instead of doing

return export { fullName, sayHi, sayHello, sayGoodBye }

just do

Object.assign(this, { fullName, sayHi, sayHello, sayGoodBye })

or this will actually work too

return { fullName, sayHi, sayHello, sayGoodBye }

And now you've explicitly created your instance with some locals.

These are known as factory functions, and they're used all the time. If you omit the export keyword to make it valid JS, it works out of the box:

function makeGreet(name) {
	function sayHi() {
		alert( "Hi " + name )
	}
	function sayHello() {
		alert( "Hello " + name )
	}
	function sayGoodBye() {
		alert( "Good bye " + name )
	}
	return { sayHi, sayHello, sayGoodBye }
}

const greeter = makeGreet("Myself")
greeter.sayHi()
greeter.sayHello()
greeter.sayGoodBye()
1 Like