Home > Net >  Javascript: Passing an argument to a function within a function
Javascript: Passing an argument to a function within a function

Time:11-12

Why does it return undefined undefined is 2 years old.?

function statement(number, name, position) {
  return function(name, position){
    return `${name} ${position} is ${number} years old.`;
  }
}

let value = statement('two', 'ayen', 'what');

console.log(value());

This one returns the desirable outcome. Can somebody explain what's happening? Thanks!

let value = statement('two');

console.log(value('ayen', 'what'));

CodePudding user response:

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')
);

CodePudding user response:

In your code right now statement is returning a function that takes two parameters which will override the parameters of statement once the inner function is called.

In your first example when you called console.log(value()) the two parameters value was supposed to take are set at null because you didn't write any.

If you wrote: let value = statement('two', 'ayen', 'what') console.log(value('Hey', 'Wassup')) It would print 'Hey Wassup is two years old'

I would suggest you write your function like this:

//This is how you should write your function
//In this example the parameters of value will not be overwriting the parameters of statement

function statement(number, name, position) {
  return function(){
    return `${name} ${position} is ${number} years old.`;
  }
}

//Here value will equal to the inner function
let value = statement('two', 'ayen', 'what');

//and this time value takes no parameters
//Before when you weren't giving value parameters it was overriding ayen and what with undefined
console.log(value());

//This will return 'ayen what is two years old'

Hope this helped!

  • Related