While reading about Javascript First Class Functions here at SO, I came across this link: What is meant by 'first class object'? wherein I found this interesting example:
var men = function (objectOfAdmiration) {
return objectOfAdmiration();
};
men.isSweetHeart = true;
var women = function (objectOfAdmiration) {
return objectOfAdmiration();
};
women.isSweetHeart = true;
var aliens = function (objectOfAdmiration) {
return objectOfAdmiration();
};
function like(obj){
if (obj.isSweetHeart) {
return function (){ return "Holy TRUE!"};
}
else {
return function (){ return "Holy CRAP!"};
}
}
alert("Men like women is " + men(like(women))); // -> "Holly TRUE!"
alert("Women like men is " + women(like(men))); // -> "Holly TRUE!"
alert("Men like aliens is " + men(like(aliens))); // -> "Holly CRAP!"
alert("Aliens like women is " + aliens(like(women))); // -> "Holly TRUE!"
I need someone to explain this code, the way things r getting executed here. Especially the expression men(like(women))
and/or women(like(men))
. How is this working out to produce the final result...
Thanks in advance
Just remember your "order of operations" from high school algebra:
Parenthesis are always evaluated first. And, in the case of an expression having nested sets of parenthesis, the inner set is evaluated before the outer ones.
So, with:
men(like(women))
The like
function is first invoked with the value of the women
variable passed to it.
Whatever that function returns is then the argument that is passed to the men
function. Like this:
men( result of calling like(women) )
And, women(like(men))
is the same idea, just reversing which one is invoked first.
So, let's take this one step at a time.
men
, women
and alien
functions are actually all identical. They simply invoke
whatever you pass to them and return that result (which in this case
will always be another function). You can infer this because all they
do is stick a set of parenthesis on the end of the input argument.
They each, therefore are expecting a function to be passed (because
that's the only thing you can invoke).So, let's pay less attention to those functions and more attention to the like
function because that is the one that returns different functions to its caller.
Read the inline comments for explanations:
// Function expression that sets men to hold a function
var men = function (objectOfAdmiration) {
// This function is expecting a function to be passed to it
// because all it does is invoke what is passed and only
// functions can be invoked.
return objectOfAdmiration();
};
// Treat men like an object now and give it an isSweetHeart property with a value of true
men.isSweetHeart = true;
// Function expression that sets women to hold a function
var women = function (objectOfAdmiration) {
// This function is expecting a function to be passed to it
// because all it does is invoke what is passed and only
// functions can be invoked.
return objectOfAdmiration();
};
// Treat men like an object now and give it an isSweetHeart property with a value of true
women.isSweetHeart = true;
// Function expression that sets alients to hold a function
var aliens = function (objectOfAdmiration) {
// This function is expecting a function to be passed to it
// because all it does is invoke what is passed and only
// functions can be invoked.
return objectOfAdmiration();
};
// Function declaration for like.
// This function is expecting an object that has an isSweetHeart property.
// Since we have multiple types of objects that support that property, this
// function is polymorphic
function like(obj){
if (obj.isSweetHeart) {
// If the men or women objects are passed, this will be returned
return function (){ return "Holy TRUE!"};
}
else {
// Anything that doesn't have the isSweetHeart property or does
// but that property has a "falsey" value will end up here
return function (){ return "Holy CRAP!"};
}
}
// Invoke like(woman)...
// since the woman object does have an isSweetHeart property and that
// property has a value of true, the function that will return "Holy TRUE!"
// when it is invoked is returned.
// That function is then passed to the men function, which recieves it under
// the parameter name of "objectOfAdmiration".
// Invoking that function outputs "Holy TRUE!"
alert("Men like women is " + men(like(women))); // -> "Holy TRUE!"
// This line does just about the same as above, but in reverse and
// because the men and women functions are the same, the same output
// is produced.
alert("Women like men is " + women(like(men))); // -> "Holy TRUE!"
// Same general procedure as before, but since aliens do not even
// have an isSweetHeart property, a different function is returned
// for further processing.
alert("Men like aliens is " + men(like(aliens))); // -> "Holy CRAP!"
// This is essentially the same as the men(like(women)) function call
// except that the result of like(women) is passed to aliens, which
// Simply invokes that function.
alert("Aliens like women is " + aliens(like(women))); // -> "Holy TRUE!"