call、apply、bind 学不会,来砍我!!!!——轻生前端

395 阅读4分钟

今天我们来说一下call、apply、bind这三兄弟的功能和区别顺便自己封装一下

call

介绍一下大哥call的功能

~~不管是call、apply还是bind作用都是为了改变函数中this的指向 ,所以他们的作用其实是大同小异滴! 先说call 举个例子吧

function fn() {
        console.log(arguments)
        console.log(this)
    }

    var obj = {
        f: fn
    }

就说他吧你要是运行个fn.call(obj, 4, 4, 4)这个 按理说this应该指向'点'前边的那位,但是呢咱们用了call那可就不一样了,this就会指向call后边括号里第一个参数,当然首先咱们得保证那个函数不能是箭头函数,箭头函数嘛 不管咋样this都指向他的上级,由此还得出一个结论 this的指向的权重!!! ---箭头函数 > call(apply,bind)这三兄弟 >"点" 然后括号中除了第一个参数之外剩下的都是 传进去的参数
=====总之括号里:

”第一个参数用函数执行时this的指向 后边的参数都是传给前边函数的实参“

fn.call(obj, 4, 4, 4)他的结果就是4,4,4和obj了!

封装一个咱们自己的call

~~对了奥call apply bind 这三兄弟 都是存在Function的原型里边的,我想在座的各位应该都知道吧! 既然他存在在Function的原型里边 我们不如 ? 嘿嘿嘿自己封装一个? 说封就封!淦!

封装之前加个小插曲es6中的...是剩余运算符

let a = ['apple','banana','orange'];

console.log(...a); //apple, banana, orange

就这么用的!!

开始封装!!

    Function.prototype.myCall = function (context, ...ary) {
        var key = Symbol()
        context[key] = this
        context[key](...ary)
        delete context[key]
    }
    fn.myCall(obj, 6, 6, 6)

就这点代码就ok了 context是他的形参也就是我们需要让this指向的地方 ...ary是解构了除了第一项之后的实参

//怎么保证一个函数执行上下文是context context.qqq() qqq执行时里边的 this就是context 但是呢这个qqq很有可能会和实参里边的属性重复所以我们用了Symbol这个东西他就是一个唯一的东西 就不会重复啦为啥还要把他删了呢
delete context[key]因为这样我们会在实参obj中加一个新的属性 所以为了不改变他就再删掉他

虽然封装一个功能和call相同的函数像是在白白费力,明明用call就可以解决我们还封装,没事找个乐子嘛!也锻炼锻炼脑袋!

apply

然后咱们开始介绍老二

~~为啥说他三是三兄弟其实他们三真的很像 apply似于call 但是第二个参数是一个集合 (数组或者类数组),

fn.apply(obj, [6, 6, 6])

和call一样一样的 就是后边参数必须得是数组或者类数组,也就是说呀他传进去之后会自动把这个数组或者类数组散开,和call好像啊!所以奥老二就介绍到这里了 哈哈哈哈!

bind

介绍一下老幺吧

~~这三兄弟是不是三胞胎?bind的用法和call 一模一样 只是不是让函数立即执行的而是返回一个新函数,新函数执行时 ,里边的this 会改变成 指定的对象

看个小例子吧:

var fn2 = fn.bind(obj, 6, 6, 6)
    fn2()

让fn执行并且把fn中的this 改成了obj,还把6,6,6传给了fn 就是呀新函数执行后他的this才会变其他和call是一样滴

咱们再封装个自己的bind?

淦!来 !fn咱们还用上边的奥 就不写了

    Function.prototype.myBind = function (context, ...arg) {
        var _this = this 
        return function (...ary) {
             _this.call(context, ...arg)

        }
    }

注意奥var _this=this就是存储的就是fn函数 其实呀就是让call的返回值再加一步函数这样就可以让他运行之后他再让this指向咱们第一项的参数了

还有一个简单的方法:

Function.prototype.myBind=function(context,...arg){
            return(...ary)=>{
                this.call(context,...arg,...ary)
            }
        }

其实和上边意思是一样的 就是换成了箭头函数this就自己找他去了

结尾

学会了吧?没学会的话我要跑路的。不过apply 已经再找我麻烦了,拿着四十米的大刀追问我为啥不给他封装一个函数!!!

都看到这了还不三连?