The main reason is something called variable shadowing.
It means that if you have a variable with the same name in your closest scope, it will over-shadow and thus have priority over any variables of the same name in higher scopes.
function statement(number, name, position) {
// ^^^^ ^^^^^^^^ these are further in scope
return function(name, position){
// ^^^^ ^^^^^^^^ these are closer in scope
return `${name} ${position} is ${number} years old.`;
}
}
In your example, name and position closest in scope will always be taken, which is the parameter list of the returned function, not the parameters of the statement function.
Since you're calling the returned function without any arguments, you're effectively passing in undefined for both name and position.
The name and position in the upper scope in this situation will never be used (will always be overshadowed) so you might as well remove them.
function statement(number) {
return function(name, position){
return `${name} ${position} is ${number} years old.`;
}
}
console.log(
statement('two')('ayen', 'what')
);
If you want them to be used, you must remove the ones in the closer scope then:
function statement1(number, name, position) {
return function(){
return `${name} ${position} is ${number} years old.`;
}
}
console.log(
statement1('two', 'ayen', 'what')()
);
If you want the behavior you presumed in your question, which is that name and position will be taken from the inner scope if not available in the upper scope, you must use distinct names and add some conditionals:
function statement1(number, name, position) {
return function(name2, position2){
const n = name2 ?? name;
const p = position2 ?? position;
return `${n} ${p} is ${number} years old.`;
}
}
console.log(
statement1('two', 'ayen', 'what')()
);
console.log(
statement1('two')('ayen', 'what')
);
namefrom the inner scope overshadowsnamefrom the outer scope; same withposition. Either pass the two arguments tovalueor don’t accept parameters in the inner function.