Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Adding a computed observable via the prototype to a constructor function

I'm using Knockout.js 2.0 and I'm trying to extend the prototype of the constructor function I've created by adding a computed observable but its throwing up "self.IsSubDomain is not a function". How do I solve this error? Is there another way to extend a constructor function to solve this?

http://jsfiddle.net/StrandedPirate/J44S4/3/

Note: I know I could define the computed observable inside the constructor function's closure but I'm building an automated code generator for knockout view models and I need to be able to extend my objects through the prototype property.

like image 866
TugboatCaptain Avatar asked Apr 23 '12 22:04

TugboatCaptain


People also ask

What is Prototype constructor?

constructor. The constructor property returns a reference to the Object constructor function that created the instance object. Note that the value of this property is a reference to the function itself, not a string containing the function's name.

When an object is instantiated from a constructor function it copies the properties and methods from the prototype into the new object?

Working With Object PrototypesWhen an object is instantiated from a constructor function, it copies the properties and methods from the prototype into the new object. However, this can result in inefficient use of memory and resources.

What is the use of a constructor function in JavaScript?

A constructor is a special function that creates and initializes an object instance of a class. In JavaScript, a constructor gets called when an object is created using the new keyword. The purpose of a constructor is to create a new object and set values for any existing object properties.

What is object constructor in JavaScript?

The Object constructor turns the input into an object. Its behavior depends on the input's type. If the value is null or undefined , it will create and return an empty object. Otherwise, it will return an object of a Type that corresponds to the given value. If the value is an object already, it will return the value.

What's the difference between a prototype and a constructor?

Well, remember, the prototype's value is the constructor that created the object. After updating the prototype of the LaserModels () with RobotModels (), we also wrote over the constructor, because the constructor's value is the Function () that created the object!

How to create an object from a constructor function in JavaScript?

In the above example, function Person () is an object constructor function. To create an object from a constructor function, we use the new keyword. Note: It is considered a good practice to capitalize the first letter of your constructor function.

Why does the constructor of an object always point to itself?

Since the constructor property is a reference to the function that created the object, as long as you have a copy of the object, it will always point to the original constructor. The constructor is set by object, so changing an object constructor property will only change that specific object constructor.

What are computed observables?

That’s where computed observables come in - these are functions that are dependent on one or more other observables, and will automatically update whenever any of these dependencies change. For example, given the following view model class,


1 Answers

I also answered this in the forum.

Here's one way to do it (jsFiddle example):

<div data-bind="text: fullDomainName">test</div>
<script>
function SiteModel(rootUrl, data) {
    var self = this;
    self.rootUrl = rootUrl;
    self.DomainName = ko.observable(data.DomainName);
    self.IsSubDomain = ko.observable(data.IsSubDomain);
    self.fullDomainName = ko.computed(self.fullDomainName, self);
}

SiteModel.prototype.fullDomainName = function () {
    if (this.IsSubDomain() && this.DomainName()) { // bombs out here with "self.IsSubDomain is not a function"
        return this.DomainName() + ".myCompanyWebsite.com";
    }
    else {
        return this.DomainName();
   }
}; 

var temp = new SiteModel("someurl", { DomainName: "extraCool" });

ko.applyBindings(temp);
</script>

I've defined the function in the prototype and made it a computed observable in the constructor.

Here's a way to do it a more generic way (jsFiddle example):

<div data-bind="text: fullDomainName">test</div>
<script>
Function.prototype.computed = function() {
    this.isComputed = true;
    return this;
};
Object.prototype.makeComputeds = function() {
    for (var prop in this) {
        if (this[prop] && this[prop].isComputed) {
            this[prop] = ko.computed(this[prop], this, {deferEvaluation:true});
        }
    }
};

function SiteModel(rootUrl, data) {
    var self = this;
    self.rootUrl = rootUrl;
    self.DomainName = ko.observable(data.DomainName);
    self.IsSubDomain = ko.observable(data.IsSubDomain);
    self.makeComputeds();
}

SiteModel.prototype.fullDomainName = function () {
    if (this.IsSubDomain() && this.DomainName()) { // bombs out here with "self.IsSubDomain is not a function"
        return this.DomainName() + ".myCompanyWebsite.com";
    }
    else {
        return this.DomainName();
   }
}.computed();

var temp = new SiteModel("someurl", { DomainName: "extraCool" });

ko.applyBindings(temp);
</script>

The underlying read function of the computed will be shared via the prototype although the actual computed property won't. I suppose there could be confusion if you created some objects and then changed the function in the prototype. New objects would use the new function, but old objects wouldn't.

Since computed observables are properties, you shouldn't expect to be able to add them to existing objects through the prototype.

like image 52
Michael Best Avatar answered Sep 28 '22 22:09

Michael Best