4

I have written an observer in javascript. You can trigger Events like this:

ClassThatExtendsEvent.triggerEvent('EventName', arg1, arg2, ..., argn)

There is a variable number of arguments, with the first argument being the event name. I do as well have subscribers, that are saved in a private property of my event class. They are getting called like this:

Event.prototype.triggerEvent = function() {

  var callbacks = this._events[eventName];      
  if(callbacks !== undefined) {
    for (var i = 0, l = callbacks.length; i < l; i++) {

      // I do not need the first argument here!!!
      callbacks[i].apply(callbacks[i], arguments);
    }
  }
}

However, the subscribers do know the event name, hence it could be ommitted. But I do not know, how to remove one argument from the list (as it's not an array but seems to be some kind of object).

I also need to readd the event name, once it's been deleted, because after notfiying the direct subscribers, a global event system kicks in. This global event system needs the name.

Hence the entire function looks like this:

Event.prototype.triggerEvent = function() {

  // First we deliver to direct subscribers
  var callbacks = this._events[eventName];      
  if(callbacks !== undefined) {
    for (var i = 0, l = callbacks.length; i < l; i++) {
      // I do NOT need the first argument here!!!
      callbacks[i].apply(callbacks[i], arguments);
    }
  }

  // Now we broadcast the event to the entire system

  // I DO need the first argument here!!!

  Facade.getInstance().broadcastEvent.apply(Facade.getInstance(), arguments);      

}

How would you implement this?

3 Answers 3

12

you can "Borrow" the shift method from the Array() object like this:

cache the shift method

shift = [].shift;

then use it to take off the first element of the arguments (since it's just an array like object)

var firstArg = shift.apply(arguments); //in case you need it
.
.
.
callbacks[i].apply(callbacks[i], arguments);

and as @casablanca said,

Many methods will work with anything that behaves like an array (numeric indices and a length property)

the shift method is just one of them.

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

1 Comment

What a wicked solution!
2

Mohamed-Ted is correct, but if you do not require the first argument you can inline the manipulation of the arguments using Array.splice as follows:

callbacks[i].apply(callbacks[i], [].splice.call(arguments, 1));

where 1 indicates the position in the arguments list that you want to retain the arguments from.

Comments

2

Just create a new array with the first argument removed:

var newArgs = [];
for (var i = 1; i < arguments.length; i++) {
  newArgs.push(arguments[i]);
}

and pass the new array to apply:

callbacks[i].apply(callbacks[i], newArgs);

2 Comments

Excellent. I did not know that I can pass a new Array ... but obvious.
@shredding: JavaScript is weird. :) Many methods will work with anything that behaves like an array (numeric indices and a length property). As you mentioned, arguments is not a true array, yet it can be used just as well as a real array for apply.

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.