2012-07-18 90 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'); 

爲了保持你可以綁定信號發送的方法構造函數中的「本」方面,儘管這會爲每個實例「自己的」對象屬性創建增加內存消耗和實際執行所有原型鏈的查找(綁定方法)無論你是否需要它們,都可以創建對象。

相關問題