Call a function with parameters from an array - apply () without a context parameter?

Is there any method that calls the function, but sets the this context to the default value that it has when calling the function by executing fn() ?

This method should take an array and pass the individual elements as arguments to the function, like apply ():

 emitter = new EventEmitter(); args = ['foo', 'bar']; // This is the desired result: emitter.emit('event', args[0], args[1], ...); // I can do this using apply, but need to set the context right emitter.emit.apply(emitter, 'event', args); // How can I trim the context from this? emitter.emit.???('event', args); 

EDIT. To clarify this, I really care about the value that this will have inside the called function - it should be the "normal" context that it has when emitter.emit() executed, and not a global object or something else, otherwise this sometimes upsets the situation.

+2
source share
3 answers

Just set the first parameter for the global object (i.e. window in the browser)

In ES3 browsers, you can pass null instead, and it will automatically be changed to a global object, but this behavior has been removed in the ES5 specs .


EDIT , it looks like you just need a new function:

 EventEmitter.prototype.emitArgs = function(event, args) { this.emit.apply(this, [event].concat(args)); } 

which you can just call:

 emitter.emitArgs('event', args); 

( EDIT thanks to @Esalija for [].concat )

+4
source

You can pass null or undefined if you don't need context. Inside the function, this will refer to the global object if in non-strict mode and null respectively undefined in strict mode .

The default context for a function is hard to define

 function f() { return this }; a = { b: f } c = ab; console.log(f()); # window console.log(ab()); # a console.log(c()); # window 

Which one is the "right" context?

In your case, you can consider the utility function

 /* you might call it something else */ emitter.emit_all = function (event, args) { return this.emit.apply(this, [event].concat(args)); } 
+5
source

This is solved by the built-in variable of variable arguments.

 var EventEmitter = window.EventEmitter = function(){ //this.emit = this.emit.bind(this);//bind emit to "this" return this; }; EventEmitter.prototype.isMe = function(obj){ return obj === this; }; EventEmitter.prototype.emit = function(eventName){ var input = Array.prototype.slice.call(arguments, 1); console.log("this:%O, Emitting event:%s, with arguments:%O", this, eventName,input); }; emitter = new EventEmitter(); emitter.emit('magicEvent', 'Zelda Con', 'Zork Meetup', 'etc'); 

To maintain the "this" context, you could bind the emit method in the constructor, although this would create for each object's own property, increasing memory consumption and practically doing all the prototype search checks (for related methods) when creating the object regardless if you need them or no.

0
source

All Articles