[js] underscore 的 bind 与 bindAll , backbone 的 on 与 listenTo

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所执行的自定义函数。

转载于:https://www.cnblogs.com/qingmingsang/articles/6946958.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值