美文网首页
理解js的 call(),apply(),bind()和模拟实现

理解js的 call(),apply(),bind()和模拟实现

作者: 果粒橙没有粒 | 来源:发表于2019-08-07 15:47 被阅读0次

    1,

    首先call()、apply()、bind() 都是用来重定义 this 这个对象的

    例子1:


    <!DOCTYPE html>

    <html lang="en">

    <head>

        <meta charset="UTF-8">

        <meta name="viewport" content="width=device-width, initial-scale=1.0">

        <meta http-equiv="X-UA-Compatible" content="ie=edge">

        <title>call</title>

    </head>

    <body>

    </body>

    <script>

        var name="盖伦";

        var sex="男";

        var character={

            name: "艾希",

            character_sex: "女",

            say:function(){

                console.log(this.name + " "+ this.sex)

            }

        }

        console.log(character.name)

        character.say();

    </script>

    </html>


    结果:

    1

    如果把say里面的console.log改以下

    console.log(this.name + " "+ this.character_sex)

    结果:

    2

    这样的结果是因为this的指向问题,say里面this的指向是character这个对象,然后character.里没有定义sex。call和apply()、bind()都可改变this指向

    列子:


    <!DOCTYPE html>

    <html lang="en">

    <head>

        <meta charset="UTF-8">

        <meta name="viewport" content="width=device-width, initial-scale=1.0">

        <meta http-equiv="X-UA-Compatible" content="ie=edge">

        <title>call</title>

    </head>

    <body>

    </body>

    <script>

        var gailun={

            name:"盖伦",

            sex:"男"

        }

        var character={

            name: "艾希",

            character_sex: "女",

            say:function(){

                console.log(this.name + " "+ this.sex)

            }

        }

        character.say.call(gailun)

    </script>

    </html>


    结果:

    通过call()就将原来指向character的this变成指向gailun,bind(),apply(),通用会改变this指向。

    3

    2,call()和apply()的区别

    call()方法接受的是一个参数列表,而apply()方法接受的是一个包含多个参数的数组

    列子:


    <!DOCTYPE html>

    <html lang="en">

    <head>

        <meta charset="UTF-8">

        <meta name="viewport" content="width=device-width, initial-scale=1.0">

        <meta http-equiv="X-UA-Compatible" content="ie=edge">

        <title>call</title>

    </head>

    <body>

    </body>

    <script>

        var gailun={

            name:"盖伦",

            sex:"男"

        }

        var timo={

            name:"提莫",

            sex:"未知"

        }

        var character={

            name: "艾希",

            character_sex: "女",

            say:function(from){

                console.log(this.name + " "+ this.sex+" "+"来自"+from)

            }

        }

        character.say.call(gailun,"德玛西亚");

        character.say.apply(timo,["班德尔城"]);

    </script>

    </html>


    结果:

    4

    假如apply()参数不是array类型,会报以下错误。

    TypeError: second argument to Function.prototype.apply must be an array

    假如:character.say.apply(null,["班德尔城"]);这样写,那么this指向了window。

    我们如果在window下这样定义:

       var name="cc"

        var sex ="男"

    那么结果应该会这样:


    cc 男 来自班德尔城


    3,bind()

    bind()方法和call,apply不一样的地方在于它返回的是一个函数

    列子:


    <!DOCTYPE html>

    <html lang="en">

    <head>

        <meta charset="UTF-8">

        <meta name="viewport" content="width=device-width, initial-scale=1.0">

        <meta http-equiv="X-UA-Compatible" content="ie=edge">

        <title>call</title>

    </head>

    <body>

    </body>

    <script>

        var name="cc"

        var sex ="男"

        var gailun={

            name:"盖伦",

            sex:"男"

        }

        var timo={

            name:"提莫",

            sex:"未知"

        }

        var character={

            name: "艾希",

            sex: "女",

            say:function(from){

                console.log(this.name + " "+ this.sex+" "+"来自"+from)

            }

        }

        character.say.call(gailun,"德玛西亚");

        character.say.apply(timo,["班德尔城"]);

        console.log(character.say.bind(gailun,"德玛西亚"))

    </script>

    </html>


    结果:

    5

    理解call(),apply(),bind()并不困难,但是面试中许多面试官都会问,“能自己模拟实现这三个函数吗?”,生活所迫那么自己实现一下。

    参考:https://github.com/mqyqingfeng/Blog/issues/11

    实践写一个call(),其他参考上面的地址


    <!DOCTYPE html>

    <html lang="en">

    <head>

        <meta charset="UTF-8">

        <meta name="viewport" content="width=device-width, initial-scale=1.0">

        <meta http-equiv="X-UA-Compatible" content="ie=edge">

        <title>myCall</title>

    </head>

    <body>

    </body>

    <script>

        var a=1;

      var bar={

          a:1

      }

      var bar2={

          a:2

      }

    function testCall(argA,argB){

      return {

            argA:argA,

            argB:argB,

            value:this.a

      }

    }

    testCall.call(bar,"c","cheng")

    Function.prototype.myCall=function(context){

        var context = context || window

        context.fn=this

        let args=[]

        for(let i =1;i<arguments.length;i++){

            args.push("arguments["+i+']')

        }

        var res = eval('context.fn('+args+')')

        delete context.fn

        return res

    }

    console.log(testCall.myCall(bar2,"c","cheng"))

    console.log(testCall.myCall(null))

    </script>

    </html>


    理解:

    首先改变this指向


    Function.prototype.call2=function(context) {

          context.fn=this;context.fn();

          delete context.fn;

    }


    如果context为空,则需要把context改成window对象

    所以改进一下


    Function.prototype.call2=function(context) {

          var context = context || window;

         context.fn=this;context.fn();

          delete context.fn;

    }


    然后处理参数,


       let args=[]

        for(let i =1;i<arguments.length;i++){

            args.push("arguments["+i+']')

        }

         var res = eval('context.fn('+args+')')


    到此完成了 call ()的模拟实现

    相关文章

      网友评论

          本文标题:理解js的 call(),apply(),bind()和模拟实现

          本文链接:https://www.haomeiwen.com/subject/oruodctx.html