2012-07-18 87 views
2

是否有任何方法调用函数,但将上下文this设置为当我通过执行fn()来调用函数时所具有的“默认”值?使用array中的参数调用函数 - 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); 

编辑:为了澄清这一点,我关心值this将在被调用函数内部 - 它需要是在执行emitter.emit()时所使用的“正常”上下文,而不是全局对象或其他任何东西。否则,这有时会破坏事物。

+0

那么什么是“正常”的上下文呢? – Esailija 2012-07-18 07:28:10

+0

当我做'emitter.emit()' - 'emitter'时,'this'的值在这种情况下是函数在其他情况下被附加到的对象。 – Niko 2012-07-18 07:31:20

+0

'someObject.emit.apply(someObject,args)'然后呢? – Esailija 2012-07-18 07:38:06

回答

4

的第一个参数就设置为全局对象(即在浏览器中window

在ES3的浏览器,你可以通过null,而不是一下子就被自动更改为全局对象,但这种行为has been removed in the ES5 specifications


编辑这听起来像你只需要一个新的功能:

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

在这一点上,你可以叫:

emitter.emitArgs('event', args); 

编辑感谢@Esalija对于[].concat

+0

它还没有被删除,但它只适用于严格模式http://es5.github.com/#C – Esailija 2012-07-18 07:31:50

+0

谢谢,但这仍然只是一个阵列的浅拷贝;) – Niko 2012-07-18 07:51:50

+1

@NIKO为什么你需要一个深复制?如果'emit'函数需要深度复制,则需要一个 - 这个代码只是一个中介。 – Alnitak 2012-07-18 07:53:08

5

如果您不关心上下文,则可以通过nullundefined。在功能内部,thiswill then refer to the global object当在非严格模式and to null respectively undefined in strict-mode。一个函数

A“默认”的背景下是很难界定的

function f() { return this }; 
a = { b: f } 
c = a.b; 

console.log(f()); # window 
console.log(a.b()); # a 
console.log(c()); # window 

其中哪一个是“正确”的背景?

你的情况,你可以考虑实用功能

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

- 我不知道传递'null'会自动将上下文更改为全局对象。 – Alnitak 2012-07-18 07:24:30

+0

谢谢,但我需要'this'来引用“正常”上下文,而不是全局对象。 – Niko 2012-07-18 07:26:59

+0

“正常”上下文_is_是全局对象。 – Alnitak 2012-07-18 07:28:09

0

这是本地功能“论据”变量解决。

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'); 

为了保持你可以绑定信号发送的方法构造函数中的“本”方面,尽管这会为每个实例“自己的”对象属性创建增加内存消耗和实际执行所有原型链的查找(绑定方法)无论你是否需要它们,都可以创建对象。

相关问题