function F() { if (!(this instanceof F)) { return new F() }; … }

后端 未结 3 1459
梦谈多话
梦谈多话 2020-12-01 01:59

What is the usage of the construct: function F() { if (!(this instanceof F)) { return new F() }; ... }?

I found this in a pty.js for Node.

相关标签:
3条回答
  • 2020-12-01 02:26

    It means that if the function was called without the new operator, it will automagically return a new instance.

    For example, if you didn't have this safeguard, and did this...

    var t = Terminal();
    

    ...then the this while executing Terminal() would point to window (or your global object, fancy non-browser guy/gal), definitely not what you want.

    By determining that this is in fact an instance of Terminal, then we can proceed. Otherwise, the safeguard returns a new object.

    Then we can simply use both forms...

    var t = Terminal(); // Will be same as `new Terminal()`
    
    0 讨论(0)
  • 2020-12-01 02:42

    Further to the great explanations in this thread, it is interesting to see what happens under the hood. The ECMAScript specification (where Javascript is based) defines a global object. This is implemented differently in different execution environments. In your typical browser, it is the window object while in Node.js it is the root object. Every function defined "in the wild" (not attached to a user created object) will become a property of the global object. In Node.js you can try:

    > function Test() {};
    > root.Test
    [Function: Test]
    

    Now, the this variable points to the object that the function is a member of. So in the example above:

    > function Test() { 
    ... console.log(this === root); 
    ... };
    > Test()
    true
    

    Same goes for your function Terminal. If you run it, this will point to the global object which is of course not an instance of Terminal!

    When calling a function using the new operator, an object is returned which will have access to a property called constructor that will point back to that function. It is something equivalent to:

    > var instance = {};
    > instance.constructor = Terminal;
    > instance.constructor();
    

    So, when the conditional fails and the Terminal function is run through the new Terminal() line, this will point to a newly created instance which is of type Terminal!

    If you want to get more technical, instance does not have a constructor property itself. It is instead linked (via the prototype chain*), to a private object** (created by the runtime) that has a constructor property pointing to the Terminal function. That private object is pointed back to by the function through a prototype property. D.Crockford presents this in pseudocode as follows:

    Terminal.prototype = {constructor: Terminal};
    

    Again, this is only when you call the function with new.

    * If a property is not found, the object will look it up at the object pointed to by the __proto__ property.

    ** (imagine something like an object called _Terminal that you cannot access by name)

    0 讨论(0)
  • 2020-12-01 02:51

    It's just to make sure it will work even if F is called without new.

    When you call F with new, in that function this is the new instance.

    Then, if this is not an instance of F (!(this instanceof F)), then that means that F was not called using new. In this case, F calls itself, now with new.

    0 讨论(0)
提交回复
热议问题