I apologize in advanced if this question is too broad. In fact it’s 4 different questions, but all related to the same piece of code, and I think they all revolve around the same principle.
I decided today, after using JS for years, to actually start learning how JS works instead of treating it like C that runs in the browser. So I starting digging into the jQuery code to see how real JS developers use the langauge. That’s when I found a block of code that looks like the code below. Note, I took this code off another stacked post here In Javascript, can you extend the DOM? . So that doesn’t mean the person that wrote this code even knew what he was talking about.
var myDOM = (function(){ // #1
var myDOM = function(elems){ // #2
return new MyDOMConstruct(elems);
},
MyDOMConstruct = function(elems) {
this.collection = elems[1] ? Array.prototype.slice.call(elems) : [elems];
return this; // #3
};
myDOM.fn = MyDOMConstruct.prototype = {
forEach : function(fn) {
var elems = this.collection;
for (var i = 0, l = elems.length; i < l; i++) {
fn( elems[i], i );
}
return this;
},
addStyles : function(styles) {
var elems = this.collection;
for (var i = 0, l = elems.length; i < l; i++) {
for (var prop in styles) {
elems[i].style[prop] = styles[prop];
}
}
return this;
}
};
return myDOM; // #4
})();
1 Why declare the function using var myDOM = (function() {})(); instead of var myDOM = function() {};
2 Why declare another function inside of the myDOM function with the exact same name? Why not put all the inner myDOM’s logic inside the outer myDOM function?
3 Why explicitly return “this”? That would have been done automatically, correct?
4 What’s going on here? Is it returning the inner myDOM’s constructor? If so, why?
Update
So most of it makes sense now. Regarding #1, I thought myDOM was being assigned the function defined after the =, but it’s not. It’s being assigned whatever that function returns. Which just happens to be a function.
I’m still not clear on #3. Yes, I understand using the function like this
console.log(MyDomConstruct('foo'))
Would display ‘undefined’. But that’s not how it’s being used. A few lines up is this
return new MyDomConstruct(elems);
I can understand explicity returning “this” if the statement went like this
return MyDomConstruct(elems);
But that’s not the case.
Why declare the function using var myDOM = (function() {})(); instead of var myDOM = function() {};
That is a such called
self-invoking anonymous functionorself-executing anonymous function. It does exactly that, it calls itself at runtime. You’ll also see the pattern:quite alot in the jQuery world. It’s the same thing, at runtime the function calls itself and guarantees that the
$sign has a reference tojQueryobject within the function body.In your snippet, the function invokes itself and returns
myDOM, a functions reference.Why declare another function inside of the myDOM function with the exact same name? Why not put all the inner myDOM’s logic inside the outer myDOM function?
That is just a convention. It could be called whatever you want it to be, maybe the author thought it is convinient to do this. The reason for this pattern is privacy & security. By returning the inner
myDOMreference aclosureis created. So the after declaring something likeyou won’t have access to
MyDOMConstruct, but your inner function do have access. That way you can protect your methods and variables. It’s also called themethod pattern. Always a good read in this contextDouglas Crockford: Javascript the good parts.Why explicitly return “this”? That would have been done automatically, correct?
No, a function will return the
undefinedvalue by default. By explicitly returnthisyou canchainthe methods like (from the above example call):since each method is returning the object of invocation, in this case
myDOM.What’s going on here? Is it returning the inner myDOM’s constructor? If so, why?
I hope that should be clear at this point.
Edit
Based on your update:
produces a new object that
inheritsfromWithout the
new keywordthethiswould not be bound to the new object. Instead it would be bound to the global object (window) and you would access global variables usingthis.