Reputation: 33880
I am trying to add a property named params
to a property named url
of a class named Page
. The property params
must be assigned the return value of an anonymous function.
The function runs just fine.
However, after assigning the return value of the function, when I check to see if the property params
has been assigned to, I see no such property in the watches window or in the console. When I try to read back the property params
from the url
property, I get undefined
.
Why is that? This happens whether I use the dot notation or the indexer notation to write / assign a value to the property. Below is my code:
var app =
{
...
};
$(document).ready(function() {
var page = new Page(app);
page.display();
});
var Page = function(app) {
this.url = window.location.href;
this.app = app;
this.url.params = (function() {
var p = { };
if (this.indexOf('?') < 0) return p;
var query = this.split('?')[1];
var pairs = query.split('&');
if (pairs === undefined || pairs.length == 0) return p;
for(var i = 0; i < pairs.length; i++) {
var pair = pairs[i].trim();
if (pair.length == 0) continue;
if (pair.indexOf('=') < 0) {
p[pair[0]] = '';
}
else {
var prop = pair.split('=');
p[prop[0]] = prop[1];
}
}
}.bind(this.url))();
this.display = function() {
debugger;
// over here, when I watch 'url', it does
// not have a 'params' property
};
};
Upvotes: 0
Views: 617
Reputation: 37318
First, the bind syntax/call is wrong. You actually don't need to use I made this work by just passing the bind
function to do something like this. Is there a specific reason you are using bind
?window.location.href
to the url.params
assignment function; also I've changed the url
to initialize as an empty object this.url = {};
.
My full working code:
var app =
{
};
$(document).ready(function() {
var page = new Page(app);
page.display();
});
var Page = function(app) {
//this.url = window.location.href;
this.url = {};
this.app = app;
this.url.params = (function(url) {
var p = { };
if (url.indexOf('?') < 0) return p;
var query = url.split('?')[1];
var pairs = query.split('&');
if (pairs === undefined || pairs.length == 0) return p;
for(var i = 0; i < pairs.length; i++) {
var pair = pairs[i].trim();
if (pair.length == 0) continue;
if (pair.indexOf('=') < 0) {
p[pair[0]] = '';
}
else {
var prop = pair.split('=');
p[prop[0]] = prop[1];
}
}
return p;
})(window.location.href); //.bind(window.location.href /*this.url*/)();
this.display = function() {
debugger;
console.log('display', this.url);
// This url (http://zikro.gr/dbg/html/js-bind.html?some=1&url=2&vars=3)
// Outputs in the console:
// Object
// params: Object
// some: "1"
// url: "2"
// vars: "3"
};
};
You can check the debugger and the console after you resume the debugger breakpoint (example with ?some=1&url=2&vars=3
url query string):
Object
params: Object
some: "1"
url: "2"
vars: "3"
And you can check my working example here: http://zikro.gr/dbg/html/js-bind.html?some=1&url=2&vars=3
EDIT
It appears that your code works quite well. You just have to initialize this.url
to be an object like this.url = {};
and then just return the p
array inside the binded function like this:
var Page = function(app) {
//this.url = window.location.href;
this.url = {};
this.href = window.location.href;
this.app = app;
this.url.params = (function(url) {
var p = { };
if (this.indexOf('?') < 0) return p;
var query = this.split('?')[1];
var pairs = query.split('&');
if (pairs === undefined || pairs.length == 0) return p;
for(var i = 0; i < pairs.length; i++) {
var pair = pairs[i].trim();
if (pair.length == 0) continue;
if (pair.indexOf('=') < 0) {
p[pair[0]] = '';
}
else {
var prop = pair.split('=');
p[prop[0]] = prop[1];
}
}
return p;
}.bind(this.href))();
this.display = function() {
debugger;
};
};
Upvotes: 0
Reputation: 19354
Assigning properties to primitive string values does not cause an error. Instead it internally promotes the string type to a String object, performs the assignment and then discards the String object.
The reason for doing this is to enable the use of String.prototype getters and methods on primitive string values. (Similar considerations apply to using Number.prototype methods on primitive number type values)
In your case
this.url = window.location.href;
sets this.url
to a primitive string value. Then when you set url.params
to a function it is internally and effectively treated as
new String(this.url).params = function () ....
for the purposes of the assignment, but the String object created gets discarded after the statement has been executed. The primitive value in this.url
does not gain properties - it is not an object data type and doesn't have properties.
Upvotes: 1
Reputation: 33880
The problem, as pointed out by @baao in the comments to the question is -- you may not add custom properties to a string literal but you can, to a String
object. There is a difference between the two.
The code snippet below proves this.
var foo = "foo";
var bar = new String("bar");
foo.foo = "foo";
bar.bar = "bar";
alert(foo.foo);
alert(bar.bar);
The fix, which was obvious, was to change the url
to being an object. This has also been demonstrated by @Christos Lytras and suggested by @baao in the comments to the original question.
var app =
{
...
};
$(document).ready(function() {
var page = new Page(app);
page.display();
});
var Page = function(app) {
this.url = { url : window.location.href };
this.app = app;
this.url.params = (function() {
var p = { };
if (this.indexOf('?') < 0) return p;
var query = this.split('?')[1];
var pairs = query.split('&');
if (pairs === undefined || pairs.length == 0) return p;
for(var i = 0; i < pairs.length; i++) {
var pair = pairs[i].trim();
if (pair.length == 0) continue;
if (pair.indexOf('=') < 0) {
p[pair[0]] = '';
}
else {
var prop = pair.split('=');
p[prop[0]] = prop[1];
}
}
return p;
}.bind(this.url.url))();
this.url.getErrorMessage = function() {
return this.params['error'];
};
this.url.getAccesToken = function() {
return this.params['access_token'];
};
this.url.search = function(pattern) {
return this.url.search(pattern);
}
this.display = function() {
...
};
};
Upvotes: 0
Reputation: 10139
You just forgot to add the return statement of the function. Fix that and your code will work pretty well :D
Upvotes: 0