2

Instructions:

  1. make this code work without modifying snippet it in any way.
  2. Use only plain old JavaScript and no third-party libraries.
  3. Write new code that enables the code below to work properly.

Hint: Feel free to extend native objects... even though it's typically a bad practice.

// Start with an object, any object
var myObject = {};


// Register an event on your object using
// an `on` method
myObject.on('myEvent', function(data) {
    // Log the data passed to the callback
    console.log(data);
});

// Trigger the event using a `trigger` method.
// Include some data when you trigger the event.
myObject.trigger('myEvent', {
    company: 'ABC Corp',
    location: 'WTC Bangalore, IN',
    website: 'http://abc.co'
});
 
// Register a different event
myObject.on('yourEvent', function() {
    console.log('yourEvent fired');
});

// Trigger the new event
myObject.trigger('yourEvent');

// Trigger all existing events using a special
// "star" identifier.
myObject.trigger('*');

// Remove one event by name
myObject.off('myEvent');

// Since we've removed the event, this should
// do nothing
myObject.trigger('myEvent');

// Remove all existing events
myObject.off();

// Since we've removed all events, this should
// do nothing
myObject.trigger('*');

Everything else went well. I'm unable to get "arguments" while implementing myObject.trigger("*"); unable to read arguments object / parameters while implementing "*" and hence throw undefined.

My JSFiddle

2
  • Is this your homework? Commented Sep 7, 2015 at 10:06
  • @hindmost - Your guess is correct, but unfortunately I can't find any answer even after googling around for more than days. I can extend it to add events but couldn't access sequence of event while "*" implement. And hence thought somebody might have better answer for it. Commented Sep 7, 2015 at 10:13

2 Answers 2

3

Disclaimer I obviously dont know what school you go to or anything, but please don't fool yourself trying to fool your teachers. With a few simple questions they'll know if you understand the material or not, and if you show up with a good answer but no knowledge to back it up, they will know what's up. I'm not accusing you of this, just a friendly word of advice of someone who has had good connections with his teachers after graduating last year ;)

So, how do we do this? Basically, you will have to add some functionality to the prototype of object, at least if you want this to affect all objects made afterwards. You can always create your own class and add the function to that prototype if you only want that class to have this functionality.

We need 3 functions added to the prototype, on, off and trigger of course. On top of that we add one extra property called events, initially an empty object. You can look at the raw code for all these in the jsfiddle, I will only go through the structure and logic of the code here.

events will hold all the handlers (functions) associated with each event. When adding an event for the first time, we add a eventName property to the events object, the value for this property is initially an empty array.

on will find (or create) the array linked to eventName in events, and push the function into the array (note we do not call the function at this time, we simply store the reference to the function in the array).

off will iterate the array of eventName, and if it finds the same function (note the ===), remove it from the array.

trigger will iterate the array of eventName and call each function. Note that the function is called with the this keyword in the function set to the object, and with the same parameters as the trigger function was called (except eventName, the first parameter, which is filtered out). Yes that means you can pass as many parameters as you want to trigger(), and they will all be passed to each handler.

I won't go into detail what things like splice, slice, ===, arguments and apply do exactly, I'm sure you can find more and better information about that elsewhere on the world wide interwebs.

There's a lot more you can do for this, like making the events object invisible through some nice uses of scoping, but that wasn't part of the question so I didn't bother with that.

If you have any more questions after looking through this, feel free to ask. I also didn't test it extensively so if you find any bugs, let me know.

EDIT: I didn't read through the comments at first, but I now also added support for the '*' wildcard. Basically the functions now check for the wildcard and will iterate all eventNames on the event object when removing or triggering. You can also remove all functions for an event by not giving a function or by giving the same wildcard, but with an eventName.

EDIT2: had some bugs running the teacher's code, realized I forgot to check for hasOwnProperty while iterating. Look that one up, it's very important when working with prototypes! I now put in the teacher's code in my jsfiddle, to show you that it works :)

jsfiddle with own code

jsfiddle with teacher code

EDIT3 - about the 'undefined' log.

The teacher's code calls .trigger 5 times, and you should see 4 console logs and as far as I can tell, they are all correct.Let me run through each trigger, and the subsequent console logs.

  1. You add a handler to myEvent, which logs the first parameter
  2. You trigger myEvent, with parameter => The parameter (the object), is logged.
  3. You add a handler to yourEvent, which logs a hardcoded string.
  4. You trigger yourEvent, no parameter => The hardcoded string is logged'
  5. You trigger * with no parameter, all handlers run => undefined is logged, since no parameters were given, data in myEvent's handler is undefined. The hardcoded string is also logged
  6. You remove the myEvent handler, trigger myEvent and confirm no functions are called
  7. You remove all event handlers, trigger * and confirm no functions are called from any events.

I honestly don't know what you expected to happen on step 5, since you give no parameter, the data is assigned undefined, that's intended behaviour.

If you want to merge the data given in step 2 so it remains on the object, then instruct so in your handler. (for example, iterate all properties of data and add them to this, then log this). Right now you simply pass it data, it gets logged, and then thrown away. You can also add a parameter in step 5, and then all handlers will receive it (including the yourEvent handlers, but that one doesn't assign nor use it).

Sign up to request clarification or add additional context in comments.

5 Comments

Thanks you, so much for reply, I'm really impressed with brief step by step explanation about how one can add, trigger and remove custom events. I’m totally agree with the fact that “modifying native object behavior is Evil”; hence added note or hint "Feel free to extend native objects...". Here’s my JSFiddle It gives me exactly same response as from your teacher code, if you noticed your "*" implementation throw undefined since it's not able to access arguments object which was original question if you carefully go through my entire question.
I think I see what you mean, but I don't know why you consider this wrong. I would have answered here but it got a bit too lengty - see my updated answer.
Also, about modifiying native behaviour: I wouldn't call it evil, but it is definitely dangerous. If you are writing a standalone app (none or minimal 3rd party libraries) then you are in full control and won't cause any issues as long as you do it correct (like we are doing here). In any kind of bigger project the best practice is probably defining your own object class and using = new MyObject instead of of = {}
(which you obvioulsy already have under your belt, looking at your code)
No problem, this was actually really good practice for myself. Thanks for accepting :)
0

document.getElementById("myBtn").addEventListener("click", displayDate);

2 Comments

Thanks for reply @Paul but I'm not looking at creating any dom event. It's custom event myEvent which will have handlers like on off trigger etc; which can be easily added using JavaScript prototype chain.
Welcome to Stack Overflow! Please consider editing your post to add more explanation about what your code does and why it will solve the problem. An answer that mostly just contains code (even if it's working) usually wont help the OP to understand their problem.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.