持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第14天,点击查看活动详情
前言
如题,这一章主要来手写一下apply,call和bind
call
先来看下原生js的call的用法
function sum (a,b) {
console.log(this)
return a+b
}
const num = sum.call('77',2,3)
console.log(num)
call改变了this指向,并接入了参数做相加操作,来看返回结果
我们继续来分析一下,call做了哪些事情
- 改变this的指向,给传递进去的第一个参数
- 后续的参数接收函数的参数,并执行操作
接下来我们针对这两点来使用js模拟下call函数
// 在原型上定义一个mycall
Function.prototype.mycall = function (thisArg,...args) {
// 接收两个参数
// this 指向 剩余的函数参数
// 1.获得要执行的函数
// 这个this就是调用mycall的函数,因为隐式绑定,谁调用函数,函数里的this就是谁
var fn = this
// 2.处理绑定thisArg
// 根据我们学的,call绑定的有两种情况,正常规则内的 或者 传入null或者undefiend的时候指向window
thisArg = (thisArg!==null && thisArg!== undefined) ? Object(thisArg):window
// 3.执行函数就是将thisArg 绑定到fn上
// 这里做一个隐式绑定
thisArg.fn = fn
// 处理参数,执行函数
let result = thisArg.fn(...args)
delete thisArg.fn
return result
}
//
let nums = sum.mycall('777',2,3)
console.log(nums)
解释一下
- 在Function的原型上绑定一个mycall函数
- 这个函数接收两部分参数,对应call函数
- 需要绑定this,形参写作thisArg
- 调用该函数的函数的参数,用ES6的剩余运算符来传入,写作形参...args
- var fn = this 接收到调用mycall函数的函数fn,因为根据隐式绑定,谁调用mycall函数它的this就是谁
- thisArg = (thisArg!==null && thisArg!== undefined) ? Object(thisArg):window 这一行,因为根据我们学的call绑定的有两种情况,正常规则内的 或者 传入null或者undefiend的时候指向window
- thisArg.fn = fn 这里我们做个隐式绑定,将fn的this指向thisArg (因为根据隐式绑定,谁调用fn函数fn的this就是谁)
- let result = thisArg.fn(...args) 执行thisArg的fn函数thisArg的fn函数并传入参数,thisArg的fn函数就是传入的fn函数
- 删除多余的参数fn
- 返回第六步的执行结果
来看下执行的结果是不是跟call函数的相似
可以看下结果多了对象中多了fn,那是因为打印的时候我们还没删除,这个无伤大雅,达到call函数的功能即可
apply
再来看下原生js的apply的用法,它和call的唯一区别就是,它是接收一个数组来接收函数的参数
function sum (a,b) {
console.log(this)
return a+b
}
const num = sum.apply('77', [2,3])
console.log(num)
apply改变了this指向,并接入了参数做相加操作,来看返回结果
我们继续来分析一下,apply做了哪些事情
- 改变this的指向,给传递进去的第一个参数
- 后续的参数接收函数的参数,并执行操作
接下来我们针对这两点来使用js模拟下apply函数
function sum (a,b) {
console.log(this)
return a+b
}
// const num = sum.apply('77', [2,3])
// console.log(num)
// 在原型上定义一个mycall
Function.prototype.myapply = function (thisArg, array) {
// 接收两个参数
// this 指向 剩余的函数参数
// 1.获得要执行的函数
// 这个this就是调用mycall的函数,因为隐式绑定,谁调用函数,函数里的this就是谁
var fn = this
// 2.处理绑定thisArg
// 根据我们学的,call绑定的有两种情况,正常规则内的 或者 传入null或者undefiend的时候指向window
thisArg = (thisArg!==null && thisArg!== undefined) ? Object(thisArg):window
// 3.执行函数就是将thisArg 绑定到fn上
// 这里做一个隐式绑定
thisArg.fn = fn
// 处理参数,执行函数
let result = thisArg.fn(...array)
delete thisArg.fn
return result
}
//
let nums = sum.myapply('777',[2,3])
console.log(nums)
//
let nums = sum.mycall('777',2,3)
console.log(nums)
解释一下
- 在Function的原型上绑定一个myapply函数
- 这个函数接收两部分参数,对应apply函数
- 需要绑定this,形参写作thisArg
- 调用该函数的函数的参数,传入一个array
- var fn = this 接收到调用myapply函数的函数fn,因为根据隐式绑定,谁调用myapply函数它的this就是谁
- thisArg = (thisArg!==null && thisArg!== undefined) ? Object(thisArg):window 这一行,因为根据我们学的call绑定的有两种情况,正常规则内的 或者 传入null或者undefiend的时候指向window
- thisArg.fn = fn 这里我们做个隐式绑定,将fn的this指向thisArg (因为根据隐式绑定,谁调用fn函数fn的this就是谁)
- let result = thisArg.fn(...args) 执行thisArg的fn函数thisArg的fn函数并传入参数,thisArg的fn函数就是传入的fn函数
- 删除多余的参数fn
- 返回第六步的执行结果
来看下执行的结果是不是跟appky函数的相似
可以看下结果多了对象中多了fn,那是因为打印的时候我们还没删除,这个无伤大雅,达到apply函数的功能即可
bind
再来看下原生js的bind的用法,它和call的唯一区别就是,它是返回一个数组
function sum (a,b) {
console.log(this)
return a+b
}
const num = sum.bind('77', 2)
let res = num(3)
console.log(res)
bind改变了this指向,并接入了参数做相加操作,来看返回结果
我们继续来分析一下,bind做了哪些事情
- 改变this的指向,给传递进去的第一个参数
- 后续的参数接收函数的参数,并执行操作
- 我们会发现,函数的形参既可以传入bind函数,也可以传入bind返回的函数里,还可以分开传
接下来我们针对这两点来使用js模拟下bind函数
function sum (a,b) {
console.log(this)
return a+b
}
// const num = sum.apply('77', [2,3])
// console.log(num)
function sum(a, b) {
console.log(this)
return a + b
}
// const num = sum.bind('77', 2)
// let res = num(3)
// console.log(res)
// 在原型上定义一个mybind
Function.prototype.mybind = function (thisArg, ...array) {
// 接收两个参数
// this 指向 剩余的函数参数
// 1.获得要执行的函数
// 这个this就是调用mycall的函数,因为隐式绑定,谁调用函数,函数里的this就是谁
var fn = this
thisArg = (thisArg !== null && thisArg !== undefined) ? Object(thisArg) : window
function proxyfunc(...args) {
// 2.处理绑定thisArg
// 根据我们学的,call绑定的有两种情况,正常规则内的 或者 传入null或者undefiend的时候指向window
// 3.执行函数就是将thisArg 绑定到fn上
// 这里做一个隐式绑定
thisArg.fn = fn
let finallyarr = [...args, ...array]
// 处理参数,执行函数
let result = thisArg.fn(...finallyarr)
delete thisArg.fn
return result
}
return proxyfunc
}
//
let nums = sum.mybind('777', 2)
console.log(nums(3))
//
let nums = sum.myapply('777',[2,3])
console.log(nums)
//
let nums = sum.mycall('777',2,3)
console.log(nums)
解释一下
- 在Function的原型上绑定一个mybind函数
- 这个函数接收两部分参数,对应bind函数
- 需要绑定this,形参写作thisArg
- 调用该函数的函数的参数,传入一个array
- var fn = this 接收到调用myapply函数的函数fn,因为根据隐式绑定,谁调用myapply函数它的this就是谁
- thisArg = (thisArg!==null && thisArg!== undefined) ? Object(thisArg):window 这一行,因为根据我们学的call绑定的有两种情况,正常规则内的 或者 传入null或者undefiend的时候指向windowm,再定义一个函数proxyfn
- thisArg.fn = fn 这里我们做个隐式绑定,将fn的this指向thisArg (因为根据隐式绑定,谁调用fn函数fn的this就是谁)
- let finallyarr = [...args, ...array] 展开运算符处理参数
- let result = thisArg.fn(...args) 执行thisArg的fn函数thisArg的fn函数并传入参数,thisArg的fn函数就是传入的fn函数
- 删除多余的参数fn
- 返回函数proxyfn
来看下执行的结果是不是跟appky函数的相似
可以看下结果多了对象中多了fn,那是因为打印的时候我们还没删除,这个无伤大雅,达到bind函数的功能即可