apply
function Person(name) {
this.name = name;
}
Person.prototype.say = function() {
console.log(this.name);
}
var wenyi = new Person('wenyi');
wenyi.say(); // wenyi
var func = wenyi.say;
func(); // 空
//因为赋值给 func 后,这里的 this 指向的是 window,而 window.name 为空。
//为了改变 this 的指向,我们可以使用 apply 方法:
func.apply(wenyi); // wenyi
在实际的使用中,我们常常看到这样的代码:
$('button').click(function() {
wenyi.say();
});
它并不美观,因为还得嵌套多一层 function 来解决 this 的指向问题.
像上面将 say 函数赋值给 func 变量后,转移的责任者并不能正确的使用原来的函数.
.bind 、 .bindAll
使用 .bind 和 .bindAll 函数可以很好的解决上面的问题:
var func1 = _.bind(wenyi.say, wenyi);
func1(); // wenyi
_.bindAll(wenyi, 'say');
var func2 = wenyi.say;
func2(); // wenyi
自己实现bind与bindAll
function bind(func, obj) {
return function () {
return func.apply(obj, Array.prototype.slice.call(arguments));
};
}
function bindAll(obj) {
var funcs = Array.prototype.slice.call(arguments, 1);
for (var i = 0; i < funcs.length; i++) {
obj[funcs[i]] = bind(obj[funcs[i]], obj);
}
return obj;
}
一个使用示例
function Person(name, age) {
this.name = name;
this.age = age;
bindAll(this, 'sayName', 'sayAge');
}
Person.prototype.sayName = function () {
console.log(this.name);
}
Person.prototype.sayAge = function () {
console.log(this.age);
}
var wenyi = new Person('wenyi', 26);
var func = wenyi.sayName;
func(); // wenyi
$('button').click(wenyi.sayAge); // 26
backbone中使用bind与bindAll
//这样做的结果是change触发的是原this.render,方法中的this依然是不可性预计
window.ProductView = Backbone.View.extrend({
initialize: function () {
_.bind(this.render, this);
this.model.bind('change', this.render);
}
});
//这是正确做法
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);
}
});
用listenTo的方式替代bind与bindAll
(function ($) {
var M = Backbone.Model.extend({
defaults: {name: "hello"}
});
var V = Backbone.View.extend({
//new V时,会跟这个视图的model绑定change事件,回调方法是视图的show方法
initialize: function () {
//给this.model绑定change事件。
//listenTo方法跟on一样是绑定事件的,listenTo多一个参数,可以设置this的指向。
this.listenTo(this.model, "change", this.show);
},
show: function (model) {
console.warn(model.get("name"));
}
});
var m = new M();
var v = new V({model: m});
//改变模型的name值时,就会触发change事件,在视图中弹出模型设置的name值。
m.set("name", "hi"); //hi
m.set("name", "bye"); //bye
})(jQuery);
backbone中on与listenTo的区别
object.listenTo(other, event, callback)
object.on(event, callback, [context]) //别名: bind
view.listenTo(model, 'change', view.render)
//上面监听方法也等价于如下代码:
model.on('change', view.render, view)
其中,第三个参数为上下文环境对象,此时它的值为view,即model对象在触发change事件时,关联view对象进行执行view.render动作。
obj1.listenTo(obj2, eventName, function)
参数obj1,obj2都为对象,
参数eventName是obj2对象触发的事件名称,
参数function为当obj2触发指定的eventName事件时,
obj1所执行的自定义函数。