javascript - Functions that return a function - TagMerge
5Functions that return a functionFunctions that return a function

Functions that return a function

Asked 1 years ago
143
5 answers

Assigning a variable to a function (without the parenthesis) copies the reference to the function. Putting the parenthesis at the end of a function name, calls the function, returning the functions return value.

Demo

function a() {
  alert('A');
}
//alerts 'A', returns undefined

function b() {
  alert('B');
  return a;
}
//alerts 'B', returns function a

function c() {
  alert('C');
  return a();
}
//alerts 'C', alerts 'A', returns undefined

alert("Function 'a' returns " + a());
alert("Function 'b' returns " + b());
alert("Function 'c' returns " + c());

In your example, you are also defining functions within a function. Such as:

function d() {
  function e() {
    alert('E');
  }
  return e;
}
d()();
//alerts 'E'

The function is still callable. It still exists. This is used in JavaScript all the time. Functions can be passed around just like other values. Consider the following:

function counter() {
  var count = 0;
  return function() {
    alert(count++);
  }
}
var count = counter();
count();
count();
count();

The function count can keep the variables that were defined outside of it. This is called a closure. It's also used a lot in JavaScript.

Source: link

45

Returning the function name without () returns a reference to the function, which can be assigned as you've done with var s = a(). s now contains a reference to the function b(), and calling s() is functionally equivalent to calling b().

// Return a reference to the function b().
// In your example, the reference is assigned to var s
return b;

Calling the function with () in a return statement executes the function, and returns whatever value was returned by the function. It is similar to calling var x = b();, but instead of assigning the return value of b() you are returning it from the calling function a(). If the function b() itself does not return a value, the call returns undefined after whatever other work is done by b().

// Execute function b() and return its value
return b();
// If b() has no return value, this is equivalent to calling b(), followed by
// return undefined;

Source: link

42

return b(); calls the function b(), and returns its result.

return b; returns a reference to the function b, which you can store in a variable to call later.

Source: link

0

const foo = function() {
   console.log("foobar");
}
foo(); // Invoke it using the variable
// foobar
function sayHello() {
   return "Hello, ";
}
function greeting(helloMessage, name) {
  console.log(helloMessage() + name);
}
// Pass `sayHello` as an argument to `greeting` function
greeting(sayHello, "JavaScript!");
// Hello, JavaScript!
function sayHello() {
   return function() {
      console.log("Hello!");
   }
}
const sayHello = function() {
   return function() {
      console.log("Hello!");
   }
}
const myFunc = sayHello();
myFunc();
// Hello!
function sayHello() {
   return function() {
      console.log("Hello!");
   }
}
sayHello()();
// Hello!

Source: link

0

Let's say you have one host object with two child objects, both with get methods, and both do exactly the same task but with a different attribute:
var accessors = {
	sortable: {
		get: function() {
			return typeof this.getAttribute('sortable') != 'undefined';
		}
	},
	droppable: {
		get: function() {
			return typeof this.getAttribute('droppable') != 'undefined';
		}
	}
};
Repeating the same code isn't ideal, so we could create one external function, passing it an attribute argument:
function getAttribute(attr) {
	return typeof this.getAttribute(attr) != 'undefined';
}
 
var accessors = {
	sortable: {
		get: function() {
			return getAttribute('sortable');
		}
	},
	droppable: {
		get: function() {
			return getAttribute('droppable');
		}
	}
};
That's a lot better but still not ideal because there's an extra, intermediate function execution every time the method is called.  What would work best is a function that returned the final function  -- that would eliminate the extra function execution with every call to get:
function generateGetMethod(attr) {
	return function() {
		return typeof this.getAttribute(attr) != 'undefined';
	};
}
 
var accessors = {
	sortable: {
		get: generateGetMethod('sortable')
	},
	droppable: {
		get: generateGetMethod('droppable')
	}
};

/* functional equivalent to the original code:

var accessors = {
	sortable: {
		get: function() {
			return typeof this.getAttribute('sortable') != 'undefined';
		}
	},
	droppable: {
		get: function() {
			return typeof this.getAttribute('droppable') != 'undefined';
		}
	}
};

*/
Hey, I have a noob question. Can’t you do the following?
function getAttribute(attr) {
	return typeof this.getAttribute(attr) != 'undefined';
}
 
var accessors = {
	sortable: {
		get: return getAttribute('sortable');
	},
	droppable: {
		get: return getAttribute('droppable');
	}
};
Can you do this?
function createKey(kStr) {
    return function(k) {
	if (k === null) {
            throw new Error("null is not a valid " + kStr);
	} else if (k === UNDEFINED) {
	    throw new Error(kStr + " must not be undefined");
	}
     };
}

Source: link

Recent Questions on javascript

    Programming Languages