Confusing JavaScript statement: “var x = new this(

2020-05-19 06:13发布

问题:

I thought I understood the concept of the JavaScript prototype object, as well as [[proto]] until I saw a few posts regarding class inheritance.

Firstly, "JavaScript OOP - the smart way" at http://amix.dk/blog/viewEntry/19038

See the implementation section:

var parent = new this('no_init');

And also "Simple JavaScript Inheritance" on John Resig's great blog.

var prototype = new this();

What does new this(); actually mean?

This statement makes no sense to me because my understand has been that this points to an object and not a constructor function. I've also tried testing statements in Firebug to figure this one out and all I receive is syntax errors.

My head has gone off into a complete spin.

Could someone please explain this in detail?

回答1:

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.



回答2:

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.



回答3:

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

The moral of the story is, not to forget functions are just like any other objects when you are not calling them.



回答4:

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();


回答5:

see this link http://www.quirksmode.org/js/this.html It will tell you about the this keyword, but I am not sure what this() is, may be its some kind of user defined function...... that you are not aware of...



回答6:

"this" means the context of the function currently running.

The code you are posting surely appears in a function that act as a method for an object. So the object is the context of the function.

"new this()" will return a clone of the current object after running its constructor function with the passed arguments.



回答7:

this() refers to the the function that the code is in, but this() would have to be within that function. Calling new this(); within a function would create a never ending loop. Calling it outside of a function would be redundant because there is no function/class set as this().



回答8:

A simpler code explaination:

class User {
  constructor() {
    this.name = '';
    this.age = '';
  }
  static getInfo() {
    let user = new this();
    console.log(user);
  } 
}

User.getInfo()

Output:

Object {
  age: "",
  name: ""
}