JS中call&bind&new三者原理

132 阅读3分钟

一、call原理

 一、call理论
 概念:call()方法使用一个指定的this值和单独给出的一个或多个参数来调用一个函数。
 语法:fun.call(thisArg, arg1, arg2, ...)
 返回值:使用调用者提供的this值的参数调用该函数的返回值,如果没有返回值,为undefined。
 作用:call就是将函数绑定到另外一个对象上去运行,且是自动调用;另外还可以改变当前函数的this的指向。  小Tip:call方法与apply方法本质差不多,就仅仅是参数传递时有所不同,apply需要以数组形式传参,call方法就直接在对象后直接传递就行啦!
 二、call原理
 1)call简单应用


 2)call方法封装
 第一步:对象借用函数,将函数绑定到对象上

 第二步:函数中参数传递

    <script>
        function f(a,b) {
            console.log("f..."+a+b)//字符串拼接
            console.log(a+b) 
        }
        Function.prototype.call = function (context) {
            context.fn = this//给obj对象加上借用函数
            // 函数传参
            console.log(arguments)//Arguments(3) [{…}, 2, 3, callee: ƒ, Symbol(Symbol.iterator): ƒ]
            let args = []
            // 去掉首参,伪数组进行遍历,推到新数组中  
            for(let i = 1;i<arguments.length;i++){
               args.push('arguments['+ i +']')//以字符串形式推进去
            }
            // console.log(args)//["arguments[1]", "arguments[2]"]

            // eval是全局函数,计算某个字符串,并执行其中的代码
            // 将括号中当做js代码,然后调用fn传递参数为args
            let r = eval('context.fn('+args+')')
            delete context.fn;//清空借用的函数
            return r 
        }
        let obj = {
            name: "wangcai"
        }
        f.call(obj,2,3) 
        console.dir(obj)//{name:"wangcai"}
    </script>

 第三步:借用函数存在返回值及当对象无借用函数时

    <script>
        function f(a,b) {
            return a+b
        }
        Function.prototype.call = function (context) {
            // context为空,即没有内容就去借用window函数
            context = context ? Object(context):window
            context.fn = this//给obj对象加上借用函数
            // 函数传参
            let args = []
            for(let i = 1;i<arguments.length;i++){
               args.push('arguments['+ i +']')//以字符串形式推进去
            }
            let r = eval('context.fn('+args+')')
            delete context.fn;//清空借用的函数
            // return r 
        }
        let obj = {
            name: "wangcai"
        }
        // 当借用函数存在返回值,需要在封装函数中也返回结果
        // 还需要打印才能得到函数返回值
        console.log(f.call(obj,2,3))//5
        console.dir(obj)//{name:"wangcai"}
    </script>

 最后:call原理完整代码,捎带着对应代码的注释

    <script>
        function f(a, b) {
            // console.log("f..........")
            // console.log(a + b)
            return a + b + 7//不要忘记借用函数存在返回值时
        }
        Function.prototype.call = function (context) {
            // 注意context为空时,借用函数属于window
            context = context ? Object(context):window
            // 让对象指向借用函数
            context.fn = this
            // 排除首参,将参数接收存到数组,遍历每一项
            let args = []
            for (i = 1; i < arguments.length; i++) {
                args.push('arguments[' + i + ']')
            }
            // 计算字符串,解析()中代码得到结果
            let r = eval('context.fn(' + args + ')')
            // 删除借用函数
            delete context.fn
            return r
        }
        let obj = {
            name: "tanni"
        }
        console.log(f.call(obj, 2, 3))
    </script>

二、bind原理

 一、bind理论
  bind本质上要返回一个新的函数,需要手动调用它才可执行。
  bind作用可分为三大点:1)bind返回一个绑定后的函数;2)改变this指向;3)函数不会自动调用,需要手动执行。
 二、bind原理
 1)bind简单应用

 2)bind方法封装
 第一步:bind函数本质上是返回一个函数,需要自己手动调用,它会被立即执行,借用了call函数或者apply函数。

 第二步:函数参数传递(bind后的参数传递)

 第三步:函数参数传递(新函数调用处的参数)

三、new原理

 一、new理论
 new是关键字,不是方法,它只能通过函数来实现,new的本质就是得到new上的那个类上面的方法和属性。  二、new原理
 1)new简单应用


 2)new关键字封装
 第一步:获取到要new上的类,利用shift将其筛选出来的。

 第二步:得到new完类之后的对象上,存在的方法和属性。

 第三步:完善new关键字的理论(当new上的那个类返回一个空对象时)