Given the following JavaScript (the relevant HTML will be posted at the bottom of the question):
var app = { // other objects from 'messages' array removed for brevity 'messages': [{ 'author': 'Maya Angelou', 'quote': "If you don't like something, change it. If you can't change it, change your attitude." }], 'textProp': 'textContent' in document.body ? 'textContent' : 'innerText', 'outputTo': document.querySelector('#output'), 'trigger': document.querySelector('#load'), 'quote': function () { var n = Math.floor(Math.random() * this.messages.length), f = document.createElement('figure'), c = document.createElement('figcaption'), frag = document.createDocumentFragment(); f[this.textProp] = this.messages[n].quote; c[this.textProp] = this.messages[n].author; frag.appendChild(f); frag.appendChild(c); this.outputTo.innerHTML = ''; this.outputTo.appendChild(frag); } }; We can call the quote() function from outside of the object using the following:
document.getElementById('load').addEventListener('click', app.quote.bind(app)); Or by simply calling the function directly (not bound as a callback to an event-handler):
app.quote(); However, I tried to create an event-handler within the object itself, using:
'clickhandler': function(){ this.trigger.addEventListener('click', this.quote); } This, of course, failed (as expected, since this here is (using an IIFE) this Window object).
I realise that this will, while the object is being created/prior to its initialisation, refer to the Window object, but is there a way I'm not seeing to create, and trigger, the event-handling within the object itself?
I realise that a large portion of my imaginary internet points comes specifically from JavaScript, but learning it accidentally leads to moments of utter confusion and inadequacy; this is not to excuse my ignorance but to explain it.
Finally, the HTML (such as it is):
<button id="load">Switch message</button> <div id="output"></div> Incidentally, I've looked at the following linked/suggested questions:
For clarity, I'm trying to create the object itself and have the event-handling created and assigned entirely within/'by' the object, without having to call its methods afterwards. That's the part where I'm stuck (and which I suspect may be impossible).
- Is it possible to reference object within the same object? - and I'm not seeing the relevance (though perhaps I'm simply tired at this point).
- Is it possible to implicitly reference a member of the parent object from within a function of a child object? - this suggests that the only possible way would be to extend the
appobject following its initialisation by adding a new method, which is do-able, but does rather go against what I want to do (and I realise that life is not fair, but even so...). - Javascript using bind within an object, how can I access object this? - deals with an event-handler, but doesn't seem directly applicable. I may be misunderstanding though.
this.trigger.addEventListener('click', this.quote.bind(this));thisrefers to depends on how you callclickhandler. If you call it "normally", likeapp.clickhandler(),thisrefers toappand you should just use.bindas suggested by epascarello . See How to access the correctthis/ context inside a callback?. Your problem has nothing to do with using object literals.key: valuepairs, wherevaluecan be any expression. But those expressions don't have access to the object itself since it does not exist yet. So in short: You can't reference the object itself during initialization.