js手撕this绑定--模拟call函数的实现

第一印--模拟call函数的实现:
第一步我们向所有函数父类的原型上也就是window的Function属性原型上添加模仿的call函数
window中的属性

//Function原型上添加模仿的call函数
Function.prototype.imicall=function (){
    console.log("模拟call:");
    //这里面的this就是sum这个函数
    let fn=this
    fn()
}
function sum(){
   console.log("i am sum:",this);
}
sum.imicall()

第一步执行结果
第二步尝试用隐式绑定把函数引用的this绑定到指定传入的对象上(简单实现)

Function.prototype.imicall=function (flag){
    console.log("模拟call:");
    let fn=this
    flag.fn=fn
    flag.fn()
    delete flag.fn
}
function sum(){
   console.log("i am sum:",this);
}
var obj={name:'xwl'}
sum.imicall(obj)

第二步执行结果
第三步考虑边界(绑定对象的选值情况)--进一步完善this绑定
首先要知道通过call函数绑定的this类型最后都为object

function test(){
    console.log(typeof this);
    console.log(this);
    console.log("i am test");
}
test.call(123)

类型说明
接下来考虑下null和undefined如何处理
我们先来看下结果
空处理
可以看到都是window,至于转换成对象,这个简单,直接用Object包裹就可以了
所以思路如下:如果flag有值且不为空那么就用Object包裹,否则就赋为window

Function.prototype.imicall=function (flag){
    console.log("模拟call:");
     if(flag!==0){
         flag=flag?Object(flag):window
     }else{
         flag=Object(flag)
     }
    let fn=this
    flag.fn=fn
    flag.fn()
    delete flag.fn
}
function sum(){
   console.log("i am sum:",this);
}
var obj={name:'xwl'}
sum.imicall(obj)

接下来我们来测试下好使不

Function.prototype.imicall=function (flag){
    console.log("模拟call:");
     if(flag!==0){
         flag=flag?Object(flag):window
     }else{
         flag=Object(flag)
     }
    let fn=this
    flag.fn=fn
    flag.fn()
    delete flag.fn
}
function sum(){
   console.log("i am sum:",this);
}
var obj={name:'xwl'}
sum.imicall(obj)
sum.imicall(null)
sum.imicall(undefined)
sum.imicall()

测试结果
第四步解决参数传递问题
首先想到的是我们能不能用函数自带的保存参数的arguments来做

Function.prototype.imicall=function (flag){
    console.log("模拟call:");
    console.log(arguments);
     if(flag!==0){
         flag=flag?Object(flag):window
     }else{
         flag=Object(flag)
     }
    let fn=this
    flag.fn=fn
    flag.fn()
    delete flag.fn
}
function sum(num1,num2){
   console.log("i am sum:",this);
   console.log(num1+num2);
}
var obj={name:'xwl'}
sum.imicall(obj,1,2)

接收结果
所以我们把下标从1开始的元素推到新的数组里,再将数组展开放到执行函数参数中

Function.prototype.imicall=function (flag){
    console.log("模拟call:");
    let args=[]
    for(var i=1;i<arguments.length;i++){
        args.push(arguments[i])
    }
     if(flag!==0){
         flag=flag?Object(flag):window
     }else{
         flag=Object(flag)
     }
    let fn=this
    flag.fn=fn
    flag.fn(...args)
    delete flag.fn
}
function sum(num1,num2){
   console.log("i am sum:",this);
   console.log(num1+num2);
}
var obj={name:'xwl'}
sum.imicall(obj,1,2)

args执行结果
感觉有点麻烦对吗?
那就用es6,需要注意的是如果我们向flag后面添加个新的参数,并对其展开,那么它会是什么?
展开类型
欸嘿,它直接就是数组,那就好办了,底下直接展开不就完事了!
展开结果
第五步别家函数都可以显示返回值,你不也得搞一个!

Function.prototype.imicall=function (flag,...args){
    console.log("模拟call:");
     if(flag!==0){
         flag=flag?Object(flag):window
     }else{
         flag=Object(flag)
     }
    let fn=this
    flag.fn=fn
    var result=flag.fn(...args)
    console.log(result);
    delete flag.fn
    return result
}
function sum(num1,num2){
   console.log("i am sum:",this);
//    console.log(num1+num2);
   return num1+num2
}
var obj={name:'xwl'}
var res=sum.imicall(obj,1,2)
console.log(res);

返回值
最后一步完整版

Function.prototype.imicall=function (flag,...args){
    console.log("模拟call:");
     if(flag!==0){
         flag=flag?Object(flag):window
     }else{
         flag=Object(flag)
     }
    let fn=this
    flag.fn=fn
    var result=flag.fn(...args)
    delete flag.fn
    return result
}
function sum(num1,num2){
   console.log("i am sum:",this);
   return num1+num2
}
var obj={name:'xwl'}
var res=sum.imicall(obj,1,2)
全部评论

相关推荐

评论
点赞
收藏
分享

创作者周榜

更多
正在热议
更多
# 春招至今,你的战绩如何? #
13730次浏览 132人参与
# AI面会问哪些问题? #
813次浏览 19人参与
# 米连集团26产品管培生项目 #
6865次浏览 223人参与
# 你的实习产出是真实的还是包装的? #
2431次浏览 47人参与
# AI时代,哪个岗位还有“活路” #
2495次浏览 49人参与
# 长得好看会提高面试通过率吗? #
2446次浏览 39人参与
# MiniMax求职进展汇总 #
24612次浏览 313人参与
# 你做过最难的笔试是哪家公司 #
1020次浏览 18人参与
# HR最不可信的一句话是__ #
914次浏览 31人参与
# 沪漂/北漂你觉得哪个更苦? #
908次浏览 29人参与
# 军工所铁饭碗 vs 互联网高薪资,你会选谁 #
7898次浏览 43人参与
# XX请雇我工作 #
51120次浏览 171人参与
# 简历中的项目经历要怎么写? #
310755次浏览 4250人参与
# 简历第一个项目做什么 #
31964次浏览 354人参与
# 不考虑薪资和职业,你最想做什么工作呢? #
152726次浏览 888人参与
# 当下环境,你会继续卷互联网,还是看其他行业机会 #
187486次浏览 1123人参与
# AI时代,哪些岗位最容易被淘汰 #
64385次浏览 857人参与
# 如果重来一次你还会读研吗 #
229937次浏览 2011人参与
# 正在春招的你,也参与了去年秋招吗? #
364032次浏览 2640人参与
# 腾讯音乐求职进展汇总 #
160794次浏览 1114人参与
# 你怎么看待AI面试 #
180527次浏览 1287人参与
# 投格力的你,拿到offer了吗? #
178044次浏览 889人参与
牛客网
牛客网在线编程
牛客网题解
牛客企业服务