作用
都是改变函数的this指向
call
用法
func.call(thisArg[, arg1[, arg2[, ...]]])
示例
var a = {
    name: 'Tom',
    age: 20,
    showInfo (str1, str2) {
        console.log(`name: ${this.name}, age: ${this.age}, str:${str1}, ${str2}`)
    }
}
var b = {
    name: 'B',
    age: 10,
    showInfo: a.showInfo
}
b.showInfo('bbb', 'hhhh') // name: B, age: 10
b.showInfo.call(a, 'aaa', 'hhh') // this 变为a   结果:name: Tom, age: 20
实现
Function.prototype.newCall = function (cxt) {
    var cxt = cxt ||  window // 防止传入的是null
    cxt.fn = this
    var args = []
    // 因为call的参数长度不定,遍历argments类数组获取参数
    for (var i =0; i< argments.length; i++) {
        args.push('argments['+ i + ']')
    }
    const res = eval('cxt.fn(' + args + ')')
    delete cxt.fn
    return res
}
apply
用法
func.apply(thisArg, [argsArray])
示例
var a = {
    name: 'Tom',
    age: 20,
    showInfo (str1, str2) {
        console.log(`name: ${this.name}, age: ${this.age}, str:${str1}, ${str2}`)
    }
}
var b = {
    name: 'B',
    age: 10,
    showInfo: a.showInfo
}
b.showInfo('bbb', 'hhhh') // name: B, age: 10
b.showInfo.apply(a, ['aaa', 'hhh']) // this 变为a   结果:name: Tom, age: 20
实现
function.prototype.newApply = function (cxt, param) {
    var cxt = cxt ||  window // 防止传入的是null
    cxt.fn = this
    var res
    if (!param) {
        res = cxt.fn()
    } else {
        var args = []
        for (var i = 0;i<param.length; i++) {
            args.push('param['+i+']')
        }
        res = eval('cxt.fn('+args+')')
    }
    delete ctx.fn
    return res
}
bind
用法
func.bind(thisArg[, arg1[, arg2[, ...]]])
示例
var a = {
    name: 'Tom',
    age: 20,
    showInfo (str1, str2) {
        console.log(`name: ${this.name}, age: ${this.age}, str:${str1}, ${str2}`)
    }
}
var b = {
    name: 'B',
    age: 10,
    showInfo: a.showInfo
}
b.showInfo('bbb', 'hhhh') // name: B, age: 10
let fn = b.showInfo.bind(a, 'aaa', 'hhh') // 这个时候不会调用
fn() // 这个时候才调用显示结果 name: Tom, age: 20, str:aaa, hhh
实现
function.prototype.newBind = function (cxt) {
    if (typeof this !== 'function') {
        throw new Error()
    }
    var self = this
    var args = Array.prototype.slice.call(arguments, 1)
    var fNOP = function () {}
    var fBound = function () {
        var bindArgs = Array.prototype.slice.call(arguments)
        return self.apply(this instanceof fNOP ? this: cxt, args.concat(bindArgs))
    }
    fNOP.prototype = this.prototype
    fBound.prototype = new fNOP()
    return fBound
}
区别
- call 和 apply用法类似,主要区别在与传入参数的不同。call接受的是是若干个参数列表,apply接受的是一个包含多个参数的数组
 - bind是创建一个函数,我们必须手动去调用它