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);
  • 相关阅读:
    155. 最小栈
    160. 相交链表
    PAT 1057 Stack
    PAT 1026 Table Tennis
    PAT 1017 Queueing at Bank
    PAT 1014 Waiting in Line
    PAT 1029 Median
    PAT 1016 Phone Bills
    PAT 1010 Radix
    PAT 1122 Hamiltonian Cycle
  • 原文地址:https://www.cnblogs.com/cazj/p/14304078.html
Copyright © 2011-2022 走看看