作用
都是改变函数的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是创建一个函数,我们必须手动去调用它