potrzebuje wyjaśnienia funkcji _.bindAll () z Underscore.js

85

Uczyłem się niektórych backbone.js i widziałem wiele przypadków, w których _.bindAll()jest używany. Przeczytałem całą stronę dokumentacji backbone.js i podkreślenia.js, aby spróbować zorientować się, co robi, ale nadal jestem bardzo niejasny co do tego, co robi. Oto wyjaśnienie podkreślenia:

_.bindAll(object, [*methodNames]) 

Wiąże szereg metod w obiekcie, określonych przez methodNames, które mają być uruchamiane w kontekście tego obiektu za każdym razem, gdy są wywoływane. Bardzo przydatne do wiązania funkcji, które będą używane jako programy obsługi zdarzeń, które w przeciwnym razie byłyby wywoływane z dość bezużytecznym this. Jeśli nie podano MethodNames, wszystkie właściwości funkcji obiektu zostaną z nim powiązane.

var buttonView = {
  label   : 'underscore',
  onClick : function(){ alert('clicked: ' + this.label); },
  onHover : function(){ console.log('hovering: ' + this.label); }
};

_.bindAll(buttonView);

jQuery('#underscore_button').bind('click', buttonView.onClick);
=> When the button is clicked, this.label will have the correct value...

Jeśli możesz tu pomóc, podając inny przykład lub jakieś ustne wyjaśnienie, wszystko byłoby wdzięczne. Próbowałem poszukać więcej samouczków lub przykładów, ale nie pojawiło się żadne, które służyłoby temu, czego potrzebowałem. Większość ludzi wydaje się po prostu wiedzieć, co robi automatycznie ...

Nik So
źródło
24
Świetne wyjaśnienie: blog.bigbinary.com/2011/08/18/…
jared_flack

Odpowiedzi:

67

var Cow = function(name) {
    this.name = name;
}
Cow.prototype.moo = function() {
    document.getElementById('output').innerHTML += this.name + ' moos' + '<br>';
}

var cow1 = new Cow('alice');
var cow2 = new Cow('bob');

cow1.moo(); // alice moos
cow2.moo(); // bob moos

var func = cow1.moo;
func(); // not what you expect since the function is called with this===window
_.bindAll(cow1, 'moo');
func = cow1.moo;
func(); // alice moos
<div id="output" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script>

Niestety faktyczna funkcjonalność „bind all” działa tylko na funkcjach bezpośrednio na obiekcie. Aby dołączyć funkcję zdefiniowaną w prototypie, należy jawnie przekazać te nazwy funkcji jako dodatkowe argumenty _.bindAll().

W każdym razie chciałeś wyjaśnienia: w zasadzie pozwala zastąpić funkcję w obiekcie funkcją, która ma tę samą nazwę i zachowanie, ale jest również powiązana z tym obiektem, więc this === theObjectnawet bez wywoływania jej jako metody ( theObject.method()).

ThiefMaster
źródło
@ThiefMaster "przekazuje te nazwy funkcji jawnie jako dodatkowe argumenty do _.bindAll ()." Przepraszam, wciąż uczę się na twoim przykładzie i spróbuj zrozumieć jego konsekwencje tutaj: więc mówisz, że funkcje zdefiniowane na prototypie nie są automatycznie wiązane z obiektem w _.bindAll i jeśli ktoś miałby to osiągnąć, należy pierwszy parametr z obiektem; drugi parametr to nazwa funkcji, JEŚLI ta funkcja została zdefiniowana w prototypie?
Nik So,
9
Ten wpis na blogu autorstwa Yehudy Katzathis bardzo dobrze wyjaśnia w JavaScript.
Henrik N,
9

Najprostsze wyjaśnienie jak dla mnie jest następne:

initialize:function () { //backbone initialize function
    this.model.on("change",this.render); //doesn't work because of the wrong context - in such a way we are searching for a render method in the window object  
    this.model.on("change",this.render,this); //works fine
    //or 
    _.bindAll(this,'render');
    this.model.on("change",this.render); //now works fine
    //after  _.bindAll we can use short callback names in model event bindings
}
Roman Yudin
źródło
-2

Spróbuj tego

<input type="button" value="submit" id="underscore_button"/>

<script>
var buttonView = {
    id     : 'underscore',
    onClick: function () {console.log('clicked: ' + this.id)},
    onHover: function () {console.log('hovering: ' + this.id)}
}
_.bindAll(buttonView, 'onClick')
$('#underscore_button').click(buttonView.onClick)
$('#underscore_button').hover(buttonView.onHover)
</script>
Wildpea
źródło