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.
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.
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.
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.
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.
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!
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.
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.
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,
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With