I'm writing a chrome extension which needs to interact with a subtree of bookmarks. There are a lot of interactions with this subtree, so I'm abstracting this logic into an object literal, like so:
var contextStore = {
'root_id': undefined,
'setup': function() {...}, // populates root_id
'add': function(name) {...}, // uses root_id
'remove': function(name) {...}, // uses root_id
// ... etc ...
};
contextStore.setup(); // only once.
contextStore.add("foo");
contextStore.add("bar");
// ... etc
So far, so good.
The trouble I'm having is caused by the asynchronous Chrome APIs (and my lack of JS-fu). To wit:
var contextStore = {
'root_id': undefined,
'setup': function() {
chrome.bookmarks.getTree(function(tree) {
// do some work to find a given folder in bookmarks.
// now I want to save that folder's id for access in other methods.
// Fail: 'this' refers to chrome.bookmarks.getTree.
this.root_id = computed_thing; // doesn't work!
});
}
// ... etc ...
};
My question is:
I looked at using the module pattern, but it doesn't seem to change things, and it's not like this code is going to be consumed by anything outside the extension.
You need to store a reference to the this
which points to the contextStore
object;
var contextStore = {
'root_id': undefined,
'setup': function() {
var that = this; // Store reference here.
chrome.bookmarks.getTree(function(tree) {
that.root_id = computed_thing; // does work!
});
}
// ... etc ...
};
This is equivalent to doing;
var contextStore = {
'root_id': undefined,
'setup': function() {
chrome.bookmarks.getTree(function(tree) {
contextStore.root_id = computed_thing; // does work!
});
}
// ... etc ...
};
However you gain the benefit of not reusing contextStore
everywhere.
The this
keyword can be bound to different things depending on how you call it. I'm not a javascript expert, but there is a good explanation at A List Apart.
The solution is to bind explicitly when calling the function using either my_function.apply(obj, [args])
, my_function.call(obj, args)
(call now) or pre-bind the function for calling later: my_function.bind(obj)
.
As a python programmer, being explicit probably makes you happy :-)
Matt's answer is eventually the better approach, as it is even more explicit, succinct and doesn't require the function to be called or prepared in a certain way. I just thought I would try to explain what was going on.
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