this.constructor.prototype — can't wholly overwrite, but can write individual props?

后端 未结 2 1829
孤城傲影
孤城傲影 2020-11-27 23:25

TL;DR? Why can\'t I overwrite a constructor\'s prototype from within the constructor?

I\'m figuring out my pattern for prototypica

相关标签:
2条回答
  • 2020-11-27 23:49

    Answer to the Specific Question

    Why can't I overwrite a constructor's prototype from within the constructor?

    It's because constructors are actually called after your object has already been instantiated. And since your object has managed to instantiate before your constructor has touched anything, your constructor has also already been assigned a "default" prototype.

    Adding properties to this.constructor.prototype seems to work -- because you're actually manipulating the constructor's pre-assigned default prototype object, which all of your instances inherit from.

    In my examples, this.constructor.prototype ended up referring to the default-assigned prototype of the constructor: so wholly overwriting it meant all new instances from that moment onward would have that new prototype -- as Bergi said, "too late" -- your current instance would not have that new prototype, as it still has the old default-assigned prototype because it's already been instantiated.

    A Better Pattern for Avoiding Nonsense

    I've come to understand, that the techniques presented in my question simply won't do. The question itself is generally misguided. By combining Bergi's wisdom with my own personal biases, I've come up with this pattern as a means to avoid having to find an answer to the original question altogether:

    function extend(p){
      return { to: function(C){ for (k in p) if (p.hasOwnProperty(k)) 
      C.prototype[k]=p[k]; return C; } };
    };
    
    var orifice = new function Orifice(){
      this.exhaust=function(){};
      this.ingest=function(){};
    };
    
    var Sphincter = extend(orifice).to(function Sphincter(){
      this.relax=function(){};
      this.tighten=function(){};
    });
    


    Here's the extend function, expanded:

    function extend(parentObject){
      return { 
        to: function(ChildConstructor){
          for (key in parentObject) 
            if (parentObject.hasOwnProperty(key)) 
              ChildConstructor.prototype[key] = parentObject[key];
          return ChildConstructor;
        }
      };
    };
    

    I used this to test that it works:

    // TESTING
    var s=new Sphincter();
    var tests=['relax','tighten','exhaust','ingest'];
    for (var i in tests) console.log("s."+tests[i]+"() is "+(tests[i]in s?"present :)":"MISSING!"));
    
    0 讨论(0)
  • 2020-11-27 23:54

    Why can't I overwrite a constructor's prototype from within the constructor?

    You can, but it's too late. The new instance has already been generated, inheriting from the old prototype. Maybe read how new works.

    I don't like how prototypes are usually defined externally from a constructor.

    That's just the way it is. You really should not setup the prototype from within the constructor - it would be executed everytime a new instance is created. That's specifically what prototypes are not supposed to be. See also Assigning prototype methods *inside* the constructor function - why not?

    and want to logically encapsulate things better.

    You might want to have a look at the various (revealing) module patterns. Or maybe even at some Class framework.

    I'm currently looking for more concrete reasons that I should not go forth with the pattern I've been presenting.

    It does not work in Internet Explorer. It would not work in any ES5-compliant environment that does not support the __proto__ property. You should never use it set a prototype on an existing object. Instead, use Object.create (or its shim) for Correct javascript inheritance - which requires that you overwrite the prototype outside of the constructor.

    My suggestion is to call your extend helper outside the constructor on it, which still has a nice syntax.

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