手动实现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);

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章