How does the following function call work in Javascript
I've been playing with the code associated with this really cool article.
In the articles code a variable is assigned a function as follows:
var messageFactory = (function() {
var that = {},
$chatMess开发者_如何学JAVAage = $('<p></p>').
addClass('chat message'),
$nick = $('<span></span>').
addClass('nick'),
$systemMessage = $('<p></p>').
addClass('system message');
var chat = function(message) {
var $filledNick = $nick.clone().
text(message.nick + ':');
return $chatMessage.clone().
append($filledNick).
append(message.text);
};
var system = function(message) {
return $systemMessage.clone().text(message.text);
};
that.chat = chat;
that.system = system;
return that;
})();
Later sub functions are called like the following,
messageFactory.system({ text: 'You changed your nick to ' + nick + '.'})
and
messageFactory.chat({ nick: 'me', text: message })
What's going on in those calls? Specifically it appears that the var messageFactory is working similar to a class definition in language like C#, and I'm missing the scope related mechanisms to how the values are being passed via the object { text: '...' ...}.
Thanks much!
The first and arguably most important thing to note is the last line. Specifically, the ()
before the ;
. What this is doing is immediately executing the anonymous function on line 1. This is important to note because messageFactory
will not contain the anonymous function, but rather whatever is returned from it. To better understand that, I'll give an example...
var x = (function(){ return "Hello!"; })();
// x will contain "Hello!", not the function.
The second thing to keep in mind is that objects in Javascript will maintain a reference to the closure that they were created in. So if you immediately execute a function like we're doing above, that will a form a closure and objects created in that closure will maintain a reference to it even after the function is done executing. Another example....
var sayHi = (function(){
var salutation = "Hello";
return function(name) {
return salutation + ", " + name + ".";
}
})();
Note again that we have an anonymous function being immediately executed. So the variable sayHi
will not contain the outside anonymous function, but rather it's return value. So sayHi
will actually contain function(name){ return salutation + ", " + name + ".";}
. You'll note that we're not passing in salutation
, but we can still access it as it's part of the closure
that this function was created in.
The final thing to understand the provided code is that in Javascript, {}
is an Object literal. It's essentially equivalent to saying new Object()
. These objects can have properties and methods the same as a C# object, which is where the .text
is coming from that you referred to.
On line 2, the code is creating an Object literal: var that = {}
. The next var creation is var chat = function(message){....
where a function is created which takes a message
parameter and does some stuff with it. Towards the end of the code, that chat
function is then assigned to the chat
property of that
and then that
is returned: that.chat = chat
and return that
.
The point of all this is that messageFactory
does not contain the function it appears to be assigned to, but rather the return
of that function. In this case, that return is actually the that
Object, which has two properties of chat
and system
. Those properties actually point back to the chat
and system
variables inside the same closure that that
was created in, which makes this all work.
The final piece is simple enough.... when you call messageFactory.chat({ text: 'something', nick:
Joe})
you're actually passing an Object
as a parameter to the chat
function inside the closure. It then references the object's nick
and text
properties to return its result.
Hope that helps. I'm not sure I explained it very well, but that's kind of how it works in my head.
It's anonymous class declaration and instantiation
http://jasonwyatt.tumblr.com/post/866536821/anonymous-classes-with-javascript-and-self-calling
精彩评论