• 《Web 前端面试指南》2、JavaScript 的 Bind 函数进阶


    使用 Bind() 设置方法中 this 对象

    //<button>获取随机的人</button>​
    //<input type="text">​
    ​
    ​var user = {
        data:[
            {name:"张三", age:37},
            {name:"李四", age:43}
        ],
        clickHandler:function (event) {
            var randomNum = ((Math.random () * 2 | 0) + 1) - 1; // 随机获取 0 或者 1
            // 从数组中取出值,赋值到 Input 文本框内
            $ ("input").val (this.data[randomNum].name + " " + this.data[randomNum].age);
        }​
    }
    
    ​// 绑定事件
    $ ("button").click (user.clickHandler);
    

    当点击的时候,会报错,因为 clickHandler 方法中的 this 指向的是 button 元素。

    为了解决这个问题,我们可以使用 bind 方法。
    使用如下代码:

    $ ("button").click (user.clickHandler.bind (user));
    

    代替之前:

    $ ("button").click (user.clickHandler);
    

    但是,在 IE9 以下和 Firefox 3.x 的浏览器中,是不支持 Bind 方法的,所以可以考虑加入如下方法。

    // 判断是否支持 Bind 方法
    if (!Function.prototype.bind) {
        Function.prototype.bind = function (oThis) {
            if (typeof this !== "function") {
                throw new TypeError (" Function.prototype.bind - 绑定错误");
            }
            var aArgs = Array.prototype.slice.call (arguments, 1),
                    fToBind = this,
                    fNOP = function () {
                    },
                    fBound = function () {
                        return fToBind.apply (this instanceof fNOP && oThis
                                ? this​
                                : oThis,
                                aArgs.concat (Array.prototype.slice.call (arguments)));
                    };
            fNOP.prototype = this.prototype;
            fBound.prototype = new fNOP ();
            return fBound;
        };
    }
    

    我们继续我们的例子,考虑如下代码:

    // 全局变量
    var data = [
        {name:"王五", age:12},
        {name:"陈六", age:14}
    ]
    
    var user = {
        // 局部变量
        data:[
            {name:"张三", age:37},
            {name:"李四", age:43}
        ],
        showData:function (event) {
            var randomNum = ((Math.random () * 2 | 0) + 1) - 1;
            console.log (this.data[randomNum].name + " " + this.data[randomNum].age);
        }
    }
    var showDataVar = user.showData;
    showDataVar (); // 王五 12 (这里说明是从 全局变量而不是局部变量中取数据)​
    

    当执行 showDataVar() 时,this 指向的是全局变量,而不是局部变量。这是因为 showDataVar() 是作为全局函数执行的,它是绑定的是全局作用域,也就是浏览器的 window 对象。

    同样,我们可以通过使用 bind 方法指定 this 的值来解决这个问题:

    // 把 showData 绑定到 user 对象
    var showDataVar = user.showData.bind (user);
    ​
    // 现在我们得到了 user 的值
    showDataVar (); // 张三 43​
    

    Bind() 可以实现借调方法 (Borrow Methods)

    我们知道在 JavaScript 中我们可以传递函数,返回函数和借调函数。Bind() 方法会使借调函数变地非常简单易用。
    如下代码:

    // 这里有个 cars 对象,它里面没有任何函数。
    var cars = {
       data:[
           {name:"黎明", age:14},
           {name:"刘德华", age:2}
       ]
    }
    ​
    // 我们可以从上面例子中借调 user 对象中 showData () 函数。
    // 我们绑定 user.showData 函数处理 cars 对象。
    cars.showData = user.showData.bind (cars);
    cars.showData (); // 黎明 14
    

    这样写的代码有个问题,就是会在 cars 对象中,新加一个函数(showData),这可能不是我们的本意,因为可能 cars 对象中此前已经有了​一个叫 showData 的属性或者函数了。我们不想意外覆盖它。在下文中会说明,最好的借调方式是使用 Apply 或者 Call。

    JavaScript 中的 Bind() 可以实现函数柯里化(Function Currying)

    柯里化:是把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参数且返回结果的新函数的技术。百度百科的定义

    首先,看以下代码,是个有三个参数的方法 greet():

    function greet (gender, age, name) {
        // 如果性别为男,使用 "先生", 否则使用 "女士"。​
        var salutation = gender === "male" ? "先生" : "女士";
        ​
        if (age > 25) {
            return "你好," + name + salutation + "。";
        }
        else {
            return "你好," + name + "。";
        }
    }
    

    接下来,我们使用 bind() 来进行函数柯里化()。

    // 因为我们不想使用 this 关键字,所以第一个参数我们传递 null。
    var greetAnAdultMale = greet.bind (null, "male", 45);
    ​
    greetAnAdultMale ("李连杰"); // "你好,李连杰先生。"​
    ​
    var greetAYoungster = greet.bind (null, "", 16);
    greetAYoungster ("成龙"); // "你好, 成龙。"​
    greetAYoungster ("李小龙"); // "你好,李小龙。"
    

    当我们使用 bind() 进行柯里化的时候,除了最后一个外,所有的参数都被预设置好了。

  • 相关阅读:
    Linux useradd 命令介绍
    lsscsi
    安装MegaCli,查看linux服务器raid信息
    ipmitool命令详解
    python 收发邮件
    angularjs 高级玩法 创建递归的模板
    我的Android进阶之旅------&gt;Android Activity的singleTask载入模式和onActivityResult方法之间的冲突
    Git实战(三)环境搭建
    使用Samba实现Linux与Windows文件共享实践
    设计模式个人备忘(享元模式,strategy, templete strategy)
  • 原文地址:https://www.cnblogs.com/lvyongbo/p/6265080.html
Copyright © 2020-2023  润新知