先具备以下条件
了解call(),apply(),bind()的用法,这里不在多讲,可自行去MDN文查阅
了解this指向,以及es6扩展运算符,一点原型链知识
(以下函数其实都是用c++写的,我们用js模拟实现)
目录
一、call()
this指向疑问:当前这个this指向谁?谁调用了就指向谁
如下面代码倒数第二行,foo调用了pm_call(),那么pm_call()这个函数里面当前的this就是foo
(不信?自行打印pm_call函数中的this)
// call
Function.prototype.pm_call = function (thisArg, ...args) {
// 获取this
let that = this
// 如果一参传入的是string/number/null/undefined调用会报错
// 所以对 这些边界进行处理,call方法对于null和undefined是会指向window
if (thisArg == undefined || thisArg == null) {
thisArg = window
} else {
thisArg = Object(thisArg)
}
// 绑定this
thisArg.fn = that
// 调用
const res = thisArg.fn(...args)
// 调用完后,删除这个方法
delete thisArg.fn
//如果有返回值
console.log(`我是pm_call返回值(当前函数${this.name}): ${res}`)
return res
}
// 测试代码
function foo() {
console.log('foo', this)
}
function sum(num1, num2) {
console.log('sum: ', num1 + num2, this, num1, num2)
return num1 + num2
}
foo.pm_call({})//可以自行写123, '123', null, undefined测试
sum.pm_call({}, 20, 30)
二、apply()
call()已经写了注释了,这里不在重复注释
//apply
Function.prototype.pm_apply = function (thisArg, args) {
let that = this
if (thisArg == undefined || thisArg == null) {
thisArg = window
} else {
thisArg = Object(thisArg)
}
//如果二参没传,就是undefined,...undefined就会报错
args = args || []
thisArg.fn = that
const res = thisArg.fn(...args)
delete thisArg.fn
return res
}
// // 测试代码
function foo() {
console.log('foo', this)
}
function sum(num1, num2) {
console.log('sum: ', num1 + num2, this, num1, num2)
return num1 + num2
}
foo.pm_apply({})
sum.pm_apply({}, [20, 30])
三、bind()
call()已经写了注释了,这里不在重复注释
//bind
Function.prototype.pm_bind = function (thisArg, ...args) {
let that = this
if (thisArg == undefined || thisArg == null) {
thisArg = window
} else {
thisArg = Object(thisArg)
}
// 为什么要返回一个函数?bind本来返回就是一个拷贝原函数
return function foo(...a) {
thisArg.fn = that
// 剩余参数合并
const arr = [...args, ...a]
const res = thisArg.fn(...arr)
delete thisArg.fn
return res
}
}
// 测试代码
function sum(n1, n2, n3, n4) {
console.log(`测试pm_bind函数:`, n1, n2, n3, n4)
}
const fun = sum.pm_bind({}, 10, 20)
fun(30, 40)
额外补充:call()和apply()的区别?
一参传的都一样,二参前者随便传,还可以接着传三参四参五参...,后者传数组