Javascript OOP - inheritance and prototyping

2019-09-14 02:37发布

问题:

I'm trying to use OOP in Javascript with inheritance and prototyping. Would you please have a look at my JSfiddel http://jsfiddle.net/Charissima/daaUK/. The last value is the problem, thank you. I cannot understand why the function drive with raceCar doesn't get the totalDistance, which a set per putTotalDistance.

        function Car () {
            var that = this;

            this.totalDistance = 0;

            this.putTotalDistance = function(distance) {
                that.totalDistance = distance;
            };

            this.getTotalDistance = function() {
                return this.totalDistance;      
            };  

            this.drive = function(distance) {
                that.totalDistance += distance;     
                return that.totalDistance;
            };

            this.privateFunc = function() { 
                return 'car ' + this.totalDistance;
            };
        };


        function RaceCar (initialDistance) {
            var that = this;

            this.prototype = new Car();
            this.drive = function(distance) {
                return that.prototype.drive(2*distance);
            };

            this.privateFunc = function() {
                return 'raceCar ' + that.getTotalDistance();
            };
        };


        RaceCar.prototype = new Car();

        car = new Car;
        raceCar = new RaceCar;          


        car.putTotalDistance(200);
        alert('car totalDistance = ' + car.drive(10) + ' - ok');

        raceCar.putTotalDistance(200);
        alert('raceCar totalDistance before drive = ' + raceCar.getTotalDistance() + ' - ok');
        alert('raceCar totalDistance after drive = ' + raceCar.drive(10) + ' Why not 220?');                

回答1:

Try this:

function Car () {    
    this.totalDistance = 0;
};

Car.prototype.putTotalDistance = function(distance) {
    this.totalDistance = distance;
};

Car.prototype.getTotalDistance = function() {
    return this.totalDistance;      
};  

Car.prototype.drive = function(distance) {
    this.totalDistance += distance;     
    return this.totalDistance;
};


function RaceCar () {};
RaceCar.prototype = new Car();
RaceCar.prototype.parent = Car.prototype;
RaceCar.prototype.drive = function(distance) {
    return this.parent.drive.call(this, (distance * 2));
};

raceCar = new RaceCar();
raceCar.putTotalDistance(200);

document.body.innerHTML = 'raceCar totalDistance after drive = ' + raceCar.drive(10);

EDIT:

As pointed out in one of the other answers, the main problem is setting the prototype inside the constructor. Instead, set it separately. In the code above, I linked the car prototype to a racecar prototype parent property and then fire the parent's drive function using call so that the context of the function is set to the racecar (via this) and then passing the argument along.



回答2:

Thank you, this works fine, but unfortunately another function I need is broken now. I created a new JSFiddle: http://jsfiddle.net/Charissima/5g6GV/

car.putTotalDistance(0);            
raceCar.putTotalDistance(100);
var drivingFunctions = [car.drive, raceCar.drive];

myText += drivingFunctions[0](10) + '<br>';
try {
    myText += drivingFunctions[1](100) + '<br>';                
}
catch(err) {
    myText += err + '<br>'
}


回答3:

Firstly var that = this; is unnecessary. In a object context this will always refer to the instance.

You also don't want to set the objects prototype inside it's own constructor.

If you want to access the prototype of a class don't try to access it through the instance.

The update fiddle

function RaceCar (initialDistance) {
    //var that = this;
    //this.prototype = new Car();

    this.drive = function(distance) {
        return RaceCar.prototype.drive(2*distance);
    };          
};

// This correctly sets the prototype
RaceCar.prototype = new Car();