理解 backbone.js 中的 bind 和 bindAll 方法,关于如何在方法中指定其中的 this,包含apply方法的说明
在backbone.js的学习过程中,被bind和bindAll弄得有点晕,这里包括underscore.js的bind和bindAll,以及JQuery提供的bind方法。
在一篇En博客中学习,写下这篇笔记
1、首先说熟悉的JQuery的bind,引用api帮助文件的内容即可很清晰地理解其使用意义和方法:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
|
dom.bind(type,[data], function (eventObject)); dom.bind(type,[data], false ); dom.bind(events); //例子 //当每个段落被点击的时候,弹出其文本: $( "p" ).bind( "click" , function (){ alert( $( this ).text() ); }); //同时绑定多个事件类型: $( '#foo' ).bind( 'mouseenter mouseleave' , function () { $( this ).toggleClass( 'entered' ); }); //同时绑定多个事件类型/处理程序: $( "button" ).bind({ click: function (){$( "p" ).slideToggle();}, mouseover: function (){$( "body" ).css( "background-color" , "red" );}, mouseout: function (){$( "body" ).css( "background-color" , "#FFFFFF" );} }); //你可以在事件处理之前传递一些附加的数据: function handler(event) { alert(event.data.foo); } $( "p" ).bind( "click" , {foo: "bar" }, handler) //通过返回false来取消默认的行为并阻止事件起泡: $( "form" ).bind( "submit" , function () { return false ; }) //通过使用 preventDefault() 方法只取消默认的行为: $( "form" ).bind( "submit" , function (event){ event.preventDefault(); }); //通过使用 stopPropagation() 方法只阻止一个事件起泡: $( "form" ).bind( "submit" , function (event){ event.stopPropagation(); }); |
2、underscore.js的apply方法
apply主要作用是让我们可以控制方法中this指代的值,下面用代码表述:
1
2
3
4
5
|
var func = function beautiful(){ alert( this + ' is beautiful' ); }; func.apply( 'Internet' ); //输出Internet is beautiful |
以上例子只帮我们理解apply的作用,实际上,apply的意义何在,请看下例:
1
2
3
4
5
6
7
8
9
10
|
function Developer(skill) { this .skill = skill; this .says = function (){ alert( this .skill + ' rocks!' ); } } var john = new Developer( 'Ruby' ); var func = john.says; func(); //输出undefined rocks! |
上例可看出,在给调用对象john中的says方法定义一个单独的方法func后,执行func,this将被认为是func所处的对象,而不是john。这时apply可以解决问题,代码如下:
1
2
3
4
5
6
7
8
9
10
|
function Developer(skill) { this .skill = skill; this .says = function (){ alert( this .skill + ' rocks!' ); } } var john = new Developer( 'Ruby' ); var func = john.says; func.apply(john); //输出Ruby rocks! |
这样做太复杂,所以需要用bind和bindAll来简化和规范化,请往下看。
3、underscore.js的bind方法
1
2
3
4
5
6
7
8
9
10
|
function Developer(skill) { this .skill = skill; this .says = function (){ alert( this .skill + ' rocks!' ); } } var john = new Developer( 'Ruby' ); var func = _.bind(john.says, john); //绑定的方法是john对象执行says方法,里面的this指代的是第二个参数john func(); //输出Ruby rocks! |
注意:_.bind()返回的值才是绑定的方法,而不会影响里面绑定的方法本身,看下例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|
window.ProductView = Backbone.View.extrend({ initialize: function () { _.bind( this .render, this ); this .model.bind( 'change' , this .render); } }); //这样做的结果是change触发的是原this.render,方法中的this依然是不可性预计 window.ProductView = Backbone.View.extrend({ initialize: function () { var f_render=_.bind( this .render, this ); this .model.bind( 'change' , f_render); } }); //这是正确做法,或者更直接简单: window.ProductView = Backbone.View.extrend({ initialize: function () { this .model.bind( 'change' , _.bind( this .render, this )); } }); //最简单当然是用_.bindAll: window.ProductView = Backbone.View.extrend({ initialize: function () { _.bindAll( this , this .render); this .model.bind( 'change' , this .render); } }); |
4、underscore.js的bindAll方法
1
2
3
4
5
6
7
8
9
10
11
12
|
function Developer(skill) { this .skill = skill; this .says = function (){ alert( this .skill + ' rocks!' ); } } var john = new Developer( 'Ruby' ); _.bindAll(john, 'says' ); //绑定的方法是john中的says方法,里面的this指代john //可以一次过指定this到多个方法:_.bindAll(john,'says','work','gohome'); var func = john.says; func(); //输出Ruby rocks! |