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.