Reputation: 63547
Ok here is a very simple JS object. Three attributes are strings, the fourth is a function.
var myStringBuilder = {
protocol: "http://",
host: "www.mysite.com",
fullPath: this.protocol + this.host + "/just/for/fun/",
getFullString: function() {
return this.fullPath;
}
}
console.log(myStringBuilder.getFullString()); // Returns "NaN/just/for/fun"
In fullPath
, this.protocol
and this.host
are both undefined. Why does this happen?
Upvotes: 2
Views: 47
Reputation: 1117
If i agree with all the valuable information in previous answers, to answer to the precise point in the question, the fullPath
property is not properly defined because it is not initialized in a function context, so this
does not refer to the object myStringBuilder.
Upvotes: 2
Reputation: 239443
Internally JavaScript objects are constructed based on a hashing algorithm. So, they keys may not logically appear in the order we define them. In this case, fullPath
gets defined first and when the value is assigned, it depends on partOne
and partTwo
where they havn't got defined yet. That is why they are undefined
while defining fullPath
.
If you must construct an Object like this, I would recommend a constructor function, like this
function MyStringBuilder() {
this.protocol = "http://";
this.host = "www.mysite.com";
this.fullPath = this.protocol + this.host + "/just/for/fun/";
}
MyStringBuilder.prototype.getFullString = function() {
return this.fullPath;
}
myStringBuilder();
The advantage of this method is that, you can customize the object creation dynamically. For example, you can pass protocol
or host
values like this
function MyStringBuilder(protocol, host) {
this.protocol = protocol || "http://";
this.host = host || "www.mysite.com";
this.fullPath = this.protocol + this.host + "/just/for/fun/";
}
with this change, you should be able to decide the protocol
and host
at runtime.
Upvotes: 2
Reputation: 27413
To get around part of the hash being undefined, you can use functions instead of calculated values. This will delay evaluation.
var myStringBuilder = {
partOne: "http://",
partTwo: "www.mysite.com",
fullPath: function(){ return this.partOne + this.partTwo + "/just/for/fun/" }
}
Upvotes: 2