2014-12-29 2 views
0

Мы используем общий шаблон в Backbone Views. У нас есть объекты событий, которые выглядят примерно так:Передача массива имен в _.bindAll - Список аргументов имеет неправильный тип

var TokenInputBaseView = Backbone.View.extend({ 

    events: { 
    'click .remove-token' : 'click_removeToken', 
    'mousedown .add-token': 'click_addToken', 
    'keydown input'  : 'keydown_input', 
    'click input'   : 'click_input', 
    'focus .token-input' : 'focus_input', 
    'blur .token-input' : 'blur_input', 
    }, 

В почти каждом случае мы хотим все обработчики событий, связанные с видом, а не к их объекту события. Итак, мы делаем это:

initialize: function(){ 
    _.bindAll(this, 'click_removeToken', ...); 
} 

Мы должны вручную перечислить каждое имя события. Было бы идеально, если бы мы могли бы просто передать массив, но подчеркивание не позволяет использовать это:

_.bindAll(this, _.values(this.events)); 

Подчеркивание хочет отдельные имена, которые передаются в качестве аргументов, а не массив. Однако, это также не работает:

_.bindAll.apply(this, _.values(this.events).unshift(this)); 

Javascript дает эту ошибку:

"Uncaught TypeError: Function.prototype.apply: Arguments list has wrong type" 

Любые идеи по хорошим способом, чтобы упростить использование bindAll так, что она не требует вручную перечисления всех функций имена для привязки?

+0

Там нет нужно сделать это. Магистраль автоматически назначит контекст экземпляра для метода, вызванного из хэша 'events' –

ответ

3

Вы передаете bindAll возврат unshift, который является длиной модифицированного массива. Вам нужно либо сохранить ссылку на массив, изменить его, а затем передать эту ссылку на apply или не использовать какой-либо другой обман:

// note, no need to bind to `this` 
_.bindAll.apply(null, [this].concat(_.values(this.events))); 

короткий пример:

var target = document.querySelector('#target'); 
 

 
var map = { 
 
    'foo': 'foo', 
 
    'bar': 'bar' 
 
}; 
 

 
function C() { 
 
    this.value = 'Value'; 
 
    _.bindAll.apply(null, [this].concat(_.values(map))); 
 
} 
 

 
C.prototype.foo = function() { 
 
    console.log('hello', this); 
 
    target.textContent = this.value + ' set by foo'; 
 
} 
 

 
C.prototype.bar = function() { 
 
    return this.value; 
 
} 
 

 
var c = new C(); 
 

 
document.addEventListener('click', c.foo);
<script src="//cdnjs.cloudflare.com/ajax/libs/underscore.js/1.7.0/underscore-min.js"></script> 
 

 
<div id="target">Click me</div>

+0

, если контекст не будет' _'? – Mathletics

+1

@Mathletics Нет, 'bindAll' фактически не использует ссылки на' this', это чистая функция. –

+0

Ах, конечно. Редактировать выглядит хорошо. – Mathletics