Confusing JavaScript statement: "var x = new this();"
What is confusing you, I think, is just where "this" is really coming from. So bear with me-- here is a very brief explanation that I hope will make it quite clear.
In JavaScript, what "this" refers to within a function is always determined at the time the function is called. When you do:
jimmy.nap();
The nap function (method) runs and receives jimmy as "this".
What objects have references to nap is irrelevant. For example:
var jimmy = {}, billy = {};
jimmy.nap = function(){ alert("zzz"); };
var jimmy_nap = jimmy.nap;
jimmy_nap(); // during this function's execution, this is *NOT* jimmy!
// it is the global object ("window" in browsers), which is given as the
// context ("this") to all functions which are not given another context.
billy.sleep = jimmy.nap;
billy.sleep(); // during this function's excution, this is billy, *NOT* jimmy
jimmy.nap(); //okay, this time, this is jimmy!
In other words, whenever you have:
var some_func = function(arg1, arg2){ /*....*/ };
// let's say obj and other_obj are some objects that came from somewhere or another
obj.some_meth = some_func;
other_obj.some_meth = some_func;
obj.some_meth(2, 3);
other_obj.some_meth(2, 3);
What it's getting "translated" into (not literally-- this is pedagogical, not about how javascript interpreters actually work at all) is something like:
var some_func = function(this, arg1, arg2){ /* ...*/ };
// let's say obj and other_obj are some objects that came from somewhere or another
obj.some_meth = some_func;
other_obj.some_meth = some_func;
obj.some_meth(obj, 2, 3);
other_obj.some_meth(other_obj, 2, 3);
So, notice how extend is used in the example on that page:
UniversityPerson = Person.extend({ /* ... */ });
Pop quiz: When extend runs, what does it think "this" refers to? Answer: That's right. "Person".
So the puzzling code above really is the same as (in that particular case):
var prototype = new Person('no_init');
Not so mysterious anymore, eh? This is possible because unlike in some languages, a JavaScript variable-- including "this"-- can hold any value, including a function such as Person.
(There is nothing that makes Person specifically a constructor. Any function can be invoked with the new keyword. If I recall the exact semantics, I think they are that when a function is called with the new keyword, it is automatically given an empty object ({}) as its context ("this") and when the function returns, the return value is that same object unless (maybe?) the function returns something else)
This is a cool question because it speaks to a pretty essential part of JavaScript's neatness or oddness (depending on how you see it).
Does that answer your question? I can clarify if necessary.
Imagine the following situation :
var inner = function () {
var obj = new this;
console.log(obj.myProperty);
};
var f1 = function () {
this.myProperty = "my Property"
}
f1.f2 = inner;
f1.f2();
Here the calling object is itself a function, so this will return a function, and we can instantiate it.
In order to use this()(not this) the outer function(the context) must itself return smth that can be instantiated(another function):
var inner = function () {
var obj = new this();
console.log(obj.myProperty);
};
var f1 = function () {
var func = function () {};
func.myProperty = 'my property';
return func;
};
f1.f2 = inner;
f1.f2();
AJS.Class
effectively* translates this:
var Person = new AJS.Class({
init: function(name) {
this.name = name;
Person.count++;
},
getName: function() {
return this.name;
}
});
Person.count = 0;
into this:
var Person = function (name) {
this.name = name;
Person.count++;
};
Person.prototype = {
getName: function() {
return this.name;
}
};
Person.extend = AJS.Class.prototype.extend;
Person.implement = AJS.Class.prototype.implement;
Person.count = 0;
Therefore, in this case, this
in AJS.Class.prototype.extend
refers to Person
, because:
Person.extend(...);
// is the same as
Person.extend.call(Person, ...);
// is the same as
AJS.Class.prototype.extend.call(Person, ...);
* There are a lot of cases I don't go over; this rewrite is for simplicity in understanding the problem.
In a javascript static
function, you can call new this()
like so,
var Class = function(){}; // constructor
Class.foo = function(){return this;} // will return the Class function which is also an object
Therefore,
Class.foo = function(){ return new this();} // Will invoke the global Class func as a constructor
This way you get a static factory method. The moral of the story is, not to forget functions are just like any other objects when you are not calling them.