Reputation: 81
I came across this answer while understanding closures by @Jacob Swartwood https://stackoverflow.com/a/6472397/3179569
and I could not understand how littleGirl
called story as if it was a function. Shouldn't it have been littleGirl();
so that the princess
function was called? Also isn't the princess function returning a key value pair, which means it's returning an object? So how can littleGirl
access a key as if it was a function? (because story
is a key right?)
I tried searching for the term returning a key value pair in javascript but didn't come up with a decent explanation. I'm hoping someone here can help me. I come with a background in Java and C++ so this is a bit confusing.
function princess() {
var adventures = [];
function princeCharming() { /* ... */ }
var unicorn = { /* ... */ },
dragons = [ /* ... */ ],
squirrel = "Hello!";
return {
story: function() {
return adventures[adventures.length - 1];
}
};
}
var littleGirl = princess();
littleGirl.story();
Upvotes: 2
Views: 61
Reputation: 2960
Or in another way, princess is just a function.
You call it with princess() and it returns something.
That something it returns, is an object like this:
{
story:function() {...}
}
This object has a function (story) inside.
A function is, after all, just some data you can pass around and assign to variables like any other data.
An object is a way of grouping different data together into a single.. well.., object
So you can put functions inside objects. And functions can return any data kind, including objects.
// set variable aFunc to some function
var aFunc=function() {...}
// call it
aFunc();
// Set an object
var anObj= {
anInt:3,
aString:"blabla",
itsFunction:aFunc
}
Call the function inside it
anObj.itsFunction();
A function returning the same object is
function getAnObj() {
return {
anInt:3,
aString:"blabla",
itsFunction:aFunc
}
}
In our case, princess is just like getAnObj, story is just like aFunction
So
princess().story();
is just like
var anObj=getAnObj();
anObj.itsFunction();
A function (princess
) returned an object (littleGirl
) that has a function inside it (story
). And you call it.
A function (getAnObj
) returned an object (anObj
) that has a function inside it (itsFunction
). And you call it.
Names..
Upvotes: 1
Reputation: 67296
Maybe if we break it down and add one thing at a time it will make more sense.
First, a function princess
that returns undefined
:
function princess() {
}
princess();
//> undefined
Next, a function that returns an object literal:
function princess() {
return {};
}
princess();
//> Object {}
Next, a function that returns an object literal with a function inside it (which returns undefined
):
function princess() {
return {
story: function {}
};
}
princess().story();
//> undefined
Next, a function that returns an object literal with a function inside that returns an array:
function princess() {
return {
story: function {
return [];
}
};
}
princess().story();
//> Array []
I think that covers most of your points. However, none of this has much to do with closures. In your example, the array adventures
is what is being closed over. This allows kind of a private
member (like with access modifier in Java).
So, finally, a function that returns an object literal with a function inside which closes over a private array:
function princess() {
var myArray = [1, 2, 3];
return {
story: function {
return myArray[myArray.length - 1]; // get the last one: 3
}
};
}
princess().story();
//> 3
Upvotes: 4
Reputation: 2217
To expand on what @asantaballa said, story
is a key with a value of function () {...}
. If you were to run console.log(littleGirl.story)
you would see function princess/<.story()
Princess could be rewritten like this...
function princess() {
var adventures = [];
function princeCharming() { /* ... */ }
var unicorn = { /* ... */ },
dragons = [ /* ... */ ],
squirrel = "Hello!";
var getAdventure = function () {
return adventures[adventures.length - 1];
};
var retObj = new Object(); // same as '{}'
retObj.story = getAdventure;
return retObj;
}
var littleGirl = princess();
littleGirl.story();
Upvotes: 2