前言
这三个方法都是改变其函数this指向的,首先给出call/apply/bind
方法的区别:
bind
:不会立即执行函数,传参形式为参数序列call
:立即执行函数,传参形式为参数序列apply
:立即执行函数,传参形式为数组
基本思路
bind
运用柯里化函数的思想,执行bind()之后,返回了一个新的函数,也是闭包的一个运用场景。
call
主要是搞清楚执行call
时,干了啥,1. 把this
方法执行,这是的this
就是那个调用call
方法的函数,这里假设为fn1
。 2. 将这个fn1
的this
指向改为你指定的那个。
apply
apply
和call
方法思路相同,只是传的参数类型不同。
上代码
let obj = {
fn(x, y) {
console.log(this, x, y)
}
}
复制代码
运用自执行函数形成闭包,以免影响全局,保护了方法。
~function anonymous(proto) {
function bind(context) {
context == null ? window : context // 考虑特殊情况null和undefined
let _this = this
let args = [].slice.call(arguments, 1)
//这里运用es5来处理,将类数组转换为数组。
//也可以写Array.prototype.slice.call(arguments, 1)
// console.log(args) [10,20]
return function proxy() {
_this.apply(context, args)
}
}
function call(context, ...args) {
/* 干了三件事:
1. 将this执行,假设为fn1
2. 将fn1中的this指向context
3. 要考虑到特殊情况,如果context不是引用类型的话,则需要自己转换
*/
context == null ? window : context
const type = typeof context
if (type !== 'object' && type !== 'function' && type !== 'symble') {
//基本数据类型
switch (type) {
case ('number'): context = new Number(context); break;
case ('string'): context = new String(context); break;
case ('Boolean'): context = new Boolean(context); break;
}
}
context.$fn = this
const res = context.$fn(...args)
return res
}
function apply(context, args) {
context == null ? window : context
const type = typeof context
if (type !== 'object' && type !== 'function' && type !== 'symble') {
//基本数据类型
switch (type) {
case ('number'): context = new Number(context); break;
case ('string'): context = new String(context); break;
case ('Boolean'): context = new Boolean(context); break;
}
}
context.$fn = this
const res = context.$fn(...args) //展开
return res
}
proto.bind = bind
proto.call = call
proto.apply = apply
}(Function.prototype)
复制代码
测试:
setTimeout(obj.fn.bind(window, 10, 20), 1000)
obj.fn.call('4', 10, 20) // String {'4', $fn: ƒ} 10 20
obj.fn.apply('4', [10, 20]) // String {'4', $fn: ƒ} 10 20
复制代码
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END