zoukankan      html  css  js  c++  java
  • 深入理解javascript中bind、apply、call

    相信做过一段时间的javascript开发的同学都或多或少用过或者见到过bind、apply、call方法。他们的作用很简单,就是改变执行函数的this指向,如果您对this了解比较模糊,您可以看这一篇博客

    作用

    首先,我们了解下,改变执行函数的this指向有哪些作用,对我们开发有哪些好处。同样,我们从一个例子开始吧。

    const obj = {
        name: '张三',
        age: 18,
        introduction: function() {
            console.log(`my name is ${this.name}, i am ${this.age} years old`)
        }
    }
    
    obj.introduction(); //my name is 张三, i am 18 years old
    
    obj.introduction.apply({name: '李四', age: 22}); //my name is 李四, i am 22 years old

    例子中,张三有一个introduction可以介绍他的信息,所以当调用obj.introduction()时,可以打印张三的个人信息,后面,我们将obj.introduction()方法绑定在了对象{name: '李四', age: 22}上,从而改变了this指向,最终打印了李四的个人信息。

    由此,我们可以看出通过改变this指向,我们可以实现代码复用。

    异同

    了解了改变this指向的作用后,我们发现bind、apply、call都是可以改变this指向,那它们有何不同之处呢,下面我们讨论下。

    1. bind

    bind方法第一个参数是需要绑定的对象,后面的参数是改变this指向方法的参数,值得注意的是bind方法的返回值仍然是一个方法,我们需要添加一对小括号才能让他执行。请看使用实例。

    const obj = {
        name: '张三',
        age: 18,
        introduction: function(sex) {
            console.log(`my name is ${this.name}, i am ${this.age} years old, my sex is ${sex}`)
        }
    }
    
    const bindFunc = obj.introduction.bind({name: '王五', age: 21}, 'men');
    bindFunc(); //my name is 王五, i am 21 years old, my sex is men

    2.  apply

    apply方法第一个参数是需要绑定的对象,第二个参数是一个数组,数组中的元素为改变this指向方法的参数,和bind不同的是,此时函数会立即执行。请看实例。

    const obj = {
        name: '张三',
        age: 18,
        introduction: function(sex) {
            console.log(`my name is ${this.name}, i am ${this.age} years old, my sex is ${sex}`)
        }
    }
    obj.introduction.apply({name: '李四', age: 22}, ['men']); //my name is 李四, i am 22 years old, my sex is men

    3. call

    call方法和apply方法极为相似,方法第一个参数是需要绑定的对象,后面的参数是改变this指向方法的参数,同样,函数也是立即执行。请看实例。

    const obj = {
        name: '张三',
        age: 18,
        introduction: function(sex) {
            console.log(`my name is ${this.name}, i am ${this.age} years old, my sex is ${sex}`)
        }
    }
    
    obj.introduction.call({name: '周六', age: 19}, 'men'); //my name is 周六, i am 19 years old, my sex is men

    关于他们的异同,这里总结了一个表格。 

    相信了解他们的用法是一个比较简单的事儿。不过,作为一个励志成为一个更优秀(tutou)的程序yuan,刨根问底是一个优良品质。

    下面,我们来分别实现这三个方法。

    1. myBind

    程序实现

    function myBind(ctx, ...rest) {
        const context = ctx || window;
        const _this = this;
    
        return function() {
            context.fn = _this;
            context.fn(...rest);
            delete context.fn;
        }
    }
    
    Function.prototype.myBind = myBind;

    2. apply

    程序实现

    function myApply(ctx, params) {
        const context = ctx || window;
    
        ctx.fn = this;
        ctx.fn(...params);
        delete ctx.fn;
    }

      Function.prototype.myApply = myApply;

    3. call

    程序实现

    function myCall(ctx, ...rest) {
        const context = ctx || window;
    
        context.fn = this;
        context.fn(rest);
        delete context.fn;
    }
    Function.prototype.myCall = myCall;

    相信上面的代码聪明的你一眼就看懂了。bind、call、apply三个方法的实现原理都是一样的,只是让我们可以通过不同的方式使用它。

    他们改变this指向的原理是通过 将需要改变this指向的方法附加在对象中执行,则方法中的this就会指向附加的对象。(在方法中,this 表示该方法所属的对象。)

    浅陋见识,不足之处,请大神指正。

  • 相关阅读:
    165. Compare Version Numbers
    164. Maximum Gap
    3、桶排序
    162. Find Peak Element
    160. Intersection of Two Linked Lists
    155. Min Stack
    154. Find Minimum in Rotated Sorted Array II
    153. Find Minimum in Rotated Sorted Array
    Linux/Unix系统编程手册 第二章:基本概念
    Linux/Unix系统编程手册 第一章:历史和标准
  • 原文地址:https://www.cnblogs.com/heshuaiblog/p/13996652.html
Copyright © 2011-2022 走看看