Javascript redefine and override existing function body

后端 未结 8 2066
难免孤独
难免孤独 2020-12-24 03:12

I am wondering can we still change the function body once it is constructed ?

     var O = function(someValue){
           this.hello = function(){
                 


        
8条回答
  •  抹茶落季
    2020-12-24 03:50

    When you create an instance of the O object using new O("somename"); you are assigning an instance method to the newly created object. When you then assign another method of the same name to O's prototype the method is already shadowed by the instance method. So:

    Object.prototype.hello // undefined
           |
           O.prototype.hello // alternate function
             |
             i.hello // original function provided in constructor
    

    JavaScript starts at the bottom of the chain and stops when it finds a match for the name. So it stops at i.hello and never sees O.prototype.hello.

    JavaScript (as of ECMAScript 5) really doesn't (as far as I am aware) give you a good way to do private variables like that that can be accessed by instance methods added after definition (either added on the instance or on the prototype). Closures get you most of the way there but if you want to be able to add methods outside of the closure that have access to closure variables you need to expose get and / or set methods that give these new methods access to the closure variables:

    // Possibility #1 - marked as private member
    var O = function(someValue) {
        this._someValue = someValue;
    };
    O.prototype.hello = function() { return "hhhh"; };
    
    var i = new O("somename");
    i.hello = function() { return "aloha," + this._someValue; };
    console.log(O.hello());  // hhhh
    console.log(i.hello());  // aloha, somename
    
    // Possibility #2 - factory function + closure with get and set methods
    var OMaker = function(someValue) {
        var realO = function() {};
        realO.prototype.getSomeValue = function() { return someValue; };
        realO.prototype.setSomeValue = function(newVal) { someValue = newVal; };
        realO.prototype.hello = function() { return "hhhh"; };
        return realO;
    };
    var O = OMaker("somename"),
                i = new O();
    i.hello = function() { return "aloha," + this.getSomeValue(); };
    console.log(O.hello());  // hhhh
    console.log(i.hello());  // aloha, somename
    
    // Possibility #3 - eschew prototype inheritance and create new objects
    var O = function(someValue) {
        return {
            getValue: function() { return someValue; },
            setValue: function(newValue) { someValue = newValue; },
            hello: function() { return "hhhh"; }
        };
    };
    var i = O(); // Note the lack of the "new" keyword
    i.hello = function() { return "aloha," + this.getSomeValue(); };
    console.log(O.hello());  // hhhh
    console.log(i.hello());  // aloha, somename
    

    You'll really want to read bobince's great answer on OOP in JavaScript for more information on the subject.

提交回复
热议问题