zoukankan      html  css  js  c++  java
  • 手动实现call、apply和bind

    如果没有传参,那么this默认指向的window 

    let a = {
        value: 1
    }
    
    function parent(sex, weight) {
        this.name = '1'
        this.age = 12
        this.sex = sex ? sex : null
        this.weight = weight ? weight : null
        console.log(123)
    }

    call的实现   call接受参数的方式  call(obj, params1, params2, ....)

    Function.prototype.myCall = function (context) {
        let currentObj = context ? context : window // 这里就是传入的第一个参数
        currentObj.fn = this // 将parent函数存起来,parent调用的myCall,此时this指向的就是该方法
        let arg = [...arguments].slice(1) // 将参数中除了第一个之后的全部存起来,第一个就是上下文要用的这个对象
        console.log(...arg)
        currentObj.fn(...arg) // 将参数传入,此时调用fn的是currentObj 即为传入的对象a,所以parent中的this会指向a
        delete context.fn // 将函数删除
    }
    // 测试代码
    // parent.myCall(a, 'mingzi', 'nianling')
    // console.log(a);

    apply的实现  apply接受参数的方式  call(obj, [params1, params2, ....])

    Function.prototype.myApply = function (context) {
        let currentObj = context ? context : window // 这里就是传入的第一个参数
        currentObj.fn = this // 将parent函数存起来,parent调用的myCall,此时this指向的就是该方法
        console.log(arguments) // [{value: 1}, ['张三', '12']]
        if(arguments[1]) {
            currentObj.fn(...arguments[1])
        } else {
            currentObj.fn()
        }
        delete currentObj.fn
    }
    // 测试代码
    // parent.myApply(a, ['boy', '50'])
    // console.log(a)

     bind()实现  

    // 实现bind()方法 调用bind()必须是一个函数   可以通过new修改this  new的优先级最高 bind()可以将参数分两次传递进来
    Function.prototype.myBind = function (context) {
        if(typeof this !== "function") { // 如果不是函数则直接抛出
            throw new TypeError('Error')
        }
        let self = this // 保存this,即为parent
        let arg = [...arguments].slice(1) // 将参数中除了第一个之后的全部存起来
        // bind()返回的是一个函数,所以可以使用new,并且会修改this的指向
        return function F() {
            if(this instanceof F) { // 如果new执行此时即为true
                return new self(...arg, ...arguments) // 返回new parent(第一次传递的参数, 第二次传递的参数) =》  arguments是执行返回的函数时的参数
            }
            return self.apply(context, [...arg, ...arguments]) // 如果没有执行new  那么直接执行parent,通过apply会将this执行最初传进来的对象a
        }
    }
    
    // 测试代码
    
    let bindResult = parent.myBind(a, 'women')
    let result = new bindResult('666')
    console.log(result);
  • 相关阅读:
    康拓展开
    P6032 选择客栈 加强版 递推
    0923考试T3 二进制,位运算
    0922考试T3 dfs序 lca 线段树 树上问题
    0921考试T2
    0922考试T1
    P3934 [Ynoi2016]炸脖龙I 树状数组 扩展欧拉定理
    0922考试T4 区间DP
    P6834 [Cnoi2020]梦原 树状数组 期望DP
    UVA1364 Knights of the Round Table Tarjan求点双联通分量+二分图染色
  • 原文地址:https://www.cnblogs.com/cazj/p/14304078.html
Copyright © 2011-2022 走看看