本节将对 js
内置对象 Function
中改变 this
指向的方法进行简单实现,在这之前先复习一下改变 javascript
函数中 this
指向的几个方法:
Function.prototype.call() --> function.call(thisArg, arg1, arg2, ...)
Function.prototype.apply() --> function.apply(thisArg, [argsArray])
Function.prototype.bind() --> function.bind(thisArg[, arg1[, arg2[, ...]]])
这里简明扼要,不是很清楚的同学,可以先学习一下具体用法。
call()
实现
-
call()
可以被所有的函数继承,所以call()
应该被定义在Function.prototype
上 -
call()
将this
绑定到第一个入参指定的对象上,并根据传入的参数执行函数
Function.prototype.myCall = function(context, ...args){
// 不传第一个参数默认为windows
context = context || window
//普通函数的this指向调用者, 故this就是要改造的那个函数
//将函数挂载到目标对象上
context.func = this
//执行函数,并保存返回值
let res = context.func(...args)
//删除之前挂载在目标对象上的函数,还原目标对象
delete context.func
//return返回值
return res
}
apply()
方法实现
apply()
与 call()
唯一的区别就是前者需要将目标函数的入参逐个传入,后者的入参则以数组形式被传入。
Function.prototype.myApply = function(context, args){
context = context || window
context.func = this
let res = context.func(...args)
delete context.func
return res
}
Math
内置函数调用 apply()
:
let arr = [1, 2, 3, 4, 5, 6]
//Math.min/max 的参数是以逗号隔开逐个传入,这里可以调用 `apply()`
Math.min.myApply(null, arr)
Math.max.myApply(null, arr)
bind()
实现
bind()
入参方式是逐个传入, 但是 bind()
返回值是一个函数
Function.prototype.myBind = function(context, ...args){
let _this = this
return function Fn(){
//因为返回值是一个函数,需要判断 new Fn() 的情况
//new 会让 this 指向这个新的对象,所以直接判断 Fn 是否在 this 的原型链上
if(this instanceof Fn){
return new _this(...args, ...arguments)
}
//调用 call 改变 this 指向
return _this.call(context, ...args, ...arguments)
}
}
bind()
实现偏函数与柯里化:
//地址生成器函数
function addressGen(){
let address = ""
[...arguments].forEach( item => {
address += item
})
return address
}
偏函数:
let guangZhou = addressGen.myBind(null, "广东省", "广州市")
let beiJing = addressGen.myBind(null, "北京市")
let liWan = guangZhou("荔湾区") //广东省广州市荔湾区
let yueXiu = guangZhou("越秀区") //广东省广州市越秀区
let haiDian = beiJing("海淀区") //北京市海淀区
柯里化:
let guangDong = addressGen.myBind(null, "广东省")
let shenZhen = guangDong.myBind(null, "深圳市")
let nanShan = shenZhen.myBind(null, "南山区")
let baiShi = nanShan("白石洲") //广东省深圳市南山区白石洲
let taoYuan = nanShan("桃源村") //广东省深圳市南山区桃源村
点赞、收藏的人已经开上兰博基尼了 (´▽`ʃ♡ƪ)
转载请注明出处!!!(https://www.jianshu.com/p/b5d39d2046ae)