手写实现bind、call、apply
2019-08-14 本文已影响0人
chrisghb
var a = {
value: 1
}
function getValue(name, age) {
console.log(name)
console.log(age)
console.log(this.value)
}
getValue.myCall(a, 'yck', '24')
getValue.myApply(a, ['yck', '24'])
// 手动实现call
Function.prototype.myCall = function (context) {
// 兼容传入null的情况(context接收的是传入的第一个参数a)
var context = context || window
// getValue.myCall调用时,将this代表的原函数getValue添加到目标对象context属性fn上,即context.fn = getValue
context.fn = this
// arguments对象并不是一个真正的数组,而是一个类数组对象
// 将 context 第二个开始的参数取出来=>('yck', '24')
var args = [...arguments].slice(1)
// 执行属性方法,相对于a.fn('yck', '24')
var result = context.fn(...args)
// 删除 fn
delete context.fn
return result
}
// 手动实现apply
Function.prototype.myApply = function (context) {
// 兼容传入null的情况(context接收的是传入的第一个参数a)
var context = context || window
// getValue.myCall调用时,将this代表的原函数getValue添加到目标对象context属性fn上,即context.fn = getValue
context.fn = this
var result
// 如果存在第二个参数,就将第二个参数展开
if (arguments[1]) {
result = context.fn(...arguments[1])
} else {
result = context.fn()
}
// 删除 fn
delete context.fn
return result
}
bind 和其他两个方法作用也是一致的,只是该方法会返回一个函数。并且我们可以通过 bind 实现柯里化。
函数柯里化:在一个函数中,首先填充几个参数,然后再返回一个新的函数的技术,称为函数的柯里化。通常可用于在不侵入函数的前提下,为函数 预置通用参数,供多次重复调用。
var a = {
name : "Cherry",
fn : function (x,y) {
console.log( x + y)
}
}
var b = a.fn
var c = b.myBind (a,1)
c(5) // 6
// 手动实现bind
Function.prototype.myBind = function (context) {
if (typeof this !== 'function') {
throw new TypeError('Error')
}
var _this = this // this代表a.fn
var args = [...arguments].slice(1) // 参数1
// 返回一个函数
return function F() {
// 如果this是F的实例
if (this instanceof F) {
return new _this(...args, ...arguments) //参数 1和5合并
}
return _this.apply(context, args.concat(...arguments))
}
}