In JavaScript, what is the proper way to reference an object's method within the object itself?
I'm messing around with Safari Extensions, and I'm trying to make an extension that changes the background color of a div based on the extension's settings. I'm using the following code:
function SwapColors() {
this.bgColorMe = safari.extension.settings.bgColorMe;
this.styleSheet = safari.extension.addContentStyleSheet(this.getStyleSheet());
this.getStyleSheet = function() {
return 'div.me {background-color: ' + this.bgColorMe + ' !important}';
}
this.rebuildStyleSheet = function() {
safari.extension.removeContentStyleSheets();
this.styleSheet = safari.extension.addContentStyleSheet(this.getStyleSheet());
}
}
var colors = new SwapColors;
safari.extension.settings.addEventListener("change", colors.rebuildStyleSheet,false);
However, Safari is complaining on line 3 (the this.styleSheet
declaration):
TypeError: Result of expression 'this.getStyleSheet' [undefined] is not a function.
I'm not really proficient in JavaScript, but it seems like this should work: this.getStyleSheet()
is defined later in the object, so it shouldn't matter, right?
Figuring that might not be true, I tried moving the this.styleSheet
declaration after getStyleSheet()
and it works: when the object is created, styleSheet
gets the correct value.
But now Safari complains about the same thing on line 11 within rebuildStyleSheet()
when I reset styleSheet
, even though getStyleSheet()
is before rebuildStyleSheet()
.
So obviously I'm missing something. How can I call getStyleSheet()
in the places it needs to be called within the object?
Edit
Based on cHao's answer, I was able to get functioning code:
function SwapColors() {
this.getStyleSheet = function() {
return 'div.me { background-color: ' + this.bgColorMe + ' !important}';
}
this.rebuildStyleSheet = function(event) {
safari.extension.removeContentStyleSheets();
if (event.key == "bgColorMe") {
this.bgColorMe = event.newValue;
}
this.styleSheet = safari.extension.addContentStyleSheet(this.getStyleSheet());
}
this.bgColorMe = safari.extension.settings.bgColorMe;
this.styleSheet = safari.extension.addContentStyleSheet(this.getStyleSheet());
}
var colors = new SwapColors;
safari.extension.settings.addEventListener("change", function(event) {
colors.rebuildStyleSheet(event);
}, false);
But this only works as long as I declare this.styleSheet
after this.getStyleSheet()
, which is contrary to how every other object-oriented language I know handles similar objects. Is this just a quirk of JavaScript, or is there something else I'm missing?
Edit 2
meder's solution turned out to be the one I was looking for. My final code:
function SwapColors() {
var that = this;
this.bgColorMe = safari.extension.settings.bgColorMe;
this.styleSheetURL = safari.extension.addContentStyleSheet(getStyleSheet());
this.styleSheet = getStyleSheet();
this.rebuildStyleSheet = function(event) {
safari.extension.removeContentStyleSheet(that.styleSheetURL);
if (event.key == "bgColorMe") {
that.bgColorMe = event.newValue;
}
styleSheetURL = safari.extension.addContentStyleSheet(getStyleSheet());
}
function getStyleSheet() {
return 'div.me { background-color: ' + that.bgColorMe + ' !important}';
}
}
var colors = new SwapColors;
safari.extension.settings.addEventListener("change", colors.rebuildStyleSheet, false);