Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JavaScript Inheritance or How is this Working?

I'm trying to achieve a degree of inheritance in JavaScript and here is what I have so far:

function Address() {
    this.address1 = ko.observable();
    this.address2 = ko.observable();
    this.country = ko.observableSafe(null, new Country(-1, '', false));
    this.city = ko.observable('');
    this.state = ko.observable();
    this.province = ko.observable('');
    this.zipCode = ko.observable();

    this.countryLookupID = '';
    this.stateLookupID = '';

    ko.computed(function () {
        var newCountry = this.country();
        if (newCountry) {
            this.countryLookupID = newCountry.id.toString();
            if (newCountry.international) {
                this.clearDomestic();
            }
            else {
                this.clearInternational();
            }
        }
        else {
            this.countryLookupID = "";


    }, this);
    ko.computed(function () {
        var newState = this.state();
        if (newState) {
            this.stateLookupID = newState.id.toString();
        }
        else {
            this.stateLookupID = "";
        }
    }, this);
}
Address.prototype.clearDomestic = function () { return true; };
Address.prototype.clearInternational = function () { return true; };

function Company() {
    this.base = Address;
    this.base(this);
    this.legalEntityID = ko.observable(0);
    this.legalEntityName = ko.observable('');
    this.isFemaleOwned = ko.observable(false);
    this.isMinorityOwned = ko.observable(false);
    this.webAddress = ko.observable();

    this.businessPhone = ko.observable();
    this.faxNumber = ko.observable();

    this.locked = ko.observable(false);

}
Company.prototype.constructor = Address;
Company.prototype.clearDomestic = function () {
    this.businessPhone('');
    this.state(null);
    this.zipCode('');
};
Company.prototype.clearInternational = function () {
    this.province('');
};

If you are unfamiliar with the Knockout framework, that is OK, as it's probably not pertinent to this discussion. I haven't seen inheritance done exactly like this anywhere that I've looked. As it currently stands, this works exactly how you think it should. When clearDomestic() is called, the correct version of the function is called in the inherited class and this points to a Company object. If I take out the base and call to base(this), it breaks.

Can anyone explain why this is working? If this is a bad practice, can someone tell me how to rewrite it so it functions the same? I don't really want to include another library to achieve this.

UPDATE

If inside Address you invoke this.clearDomestic() outside of the ko.computed, it tries to call the clearDomestic() attached to Company but then this points to an Address object and so businessPhone is no longer defined.

UPDATE 2

I've moved things around again, and I've settled on this method. It's not ideal, but it's the only way that consistently works.

function Address() {
    this.address1 = ko.observable();
    this.address2 = ko.observable();
    this.country = ko.observableSafe(null, new Country(-1, '', false));
    this.city = ko.observable('');
    this.state = ko.observable();
    this.province = ko.observable('');
    this.zipCode = ko.observable();

    this.countryLookupID = '';
    this.stateLookupID = '';
}
Address.prototype.clearDomestic = function () { return true; };
Address.prototype.clearInternational = function () { };

function Company() {
    this.legalEntityID = ko.observable(0);
    this.legalEntityName = ko.observable('');
    this.isFemaleOwned = ko.observable(false);
    this.isMinorityOwned = ko.observable(false);
    this.webAddress = ko.observable();

    this.businessPhone = ko.observable();
    this.faxNumber = ko.observable();

    this.locked = ko.observable(false);

    ko.computed(function () {
        var newCountry = this.country();
        if (newCountry) {
            this.countryLookupID = newCountry.id.toString();
            if (newCountry.international) {
                this.clearDomestic();
            }
            else {
                this.clearInternational();
            }
        }
        else {
            this.countryLookupID = "";
        }

    }, this);
    ko.computed(function () {
        var newState = this.state();
        if (newState) {
            this.stateLookupID = newState.id.toString();
        }
        else {
            this.stateLookupID = "";
        }
    }, this);
}
Company.prototype = new Address;
Company.prototype.clearDomestic = function () {
    // Since we are entering this method via Address, we need a reference back to a real company object with self.
    this.businessPhone('');
    this.state(null);
    this.zipCode('');
};
Company.prototype.clearInternational = function () {
    this.province('');
};

I'm going to have to do the logic in the newstate and newcountry in every object that inherits from Address which makes this far from ideal, but until I find a better suggestion, I'm stuck with this.

like image 784
arb Avatar asked Nov 13 '22 08:11

arb


1 Answers

I'm not sure I understand the problem exactly, but instead of this.base(this);, try calling this.base.call(this);? (in the first version of your code).

like image 85
Knio Avatar answered Nov 16 '22 04:11

Knio