改变this指向

改变this指向的三大方法

  • call

立即执行

参数传递为单个传递

  • apply

立即执行

参数传递为数组

  • bind

不立即执行,会返回一个函数,调用时才执行

参数传递可单个传递,也可传递数组

 

举例说明

复制代码
<script>
    window.color = "red"
    document.color = "yellow"
    var obj = { color: "salmon" }
    function changeColor(newColor1,newColor2) {
      console.log(this.color)
      console.log(newColor1)
      console.log(newColor2)
    }

    changeColor.call(obj,"pink","grey") //salmon pink grey
    changeColor.apply(obj,["pink","grey"]) //salmon pink grey
    var bindColor=changeColor.bind(obj,"pink","grey") //salmon pink grey
    bindColor()
    var bindColor2=changeColor.bind(obj,'blue')
    bindColor2('green','pink') //salmon blue green
</script>
复制代码

 

手写解析

  • 手写call
复制代码
    var obj = { color: "salmon" }
    function changeColor(newColor1,newColor2) {
      return{
        color:this.color,
        newColor1,newColor1,
        newColor2:newColor2
      }
    }

    var newCall=function(objarg){
      //this指向调用的方法changeCOlor
      //objarg指向传递进来的第一个参数,为想要改变的this指向,必须为一个对象
      objarg=objarg||window
      objarg.func=this //改变this指向 
      console.log(arguments)//第一个参数为改变this指向,后续参数为传的参数
      var arr=[]
      for(let i=1;i<arguments.length;i++){
        const elem=arguments[i]
        arr.push(elem)
      }
      var res=objarg.func(...arr)
      delete(objarg.func)//不能改变原对象,所以进行删除
      return res //call有返回值,最终需要返回
    }

    Function.prototype.newCall=newCall //绑定到原型上,所有函数都可以调用
    console.log("===",changeColor.newCall(obj,'red','blue')) //{color:'salmon',newColor1:'red',newColor2:'blue'}
复制代码
  • 手写call实现了,实现手写apply就只用修改传参方式不通的问题
//不用去分析获取到arr,直接解构arguments的第1项
var res=objarg.func(...arguments[1])
  var newApply=function(objarg){
      objarg=objarg||window
      objarg.func=this //改变this指向 
      var res=objarg.func(...arguments[1])
      delete(objarg.func)
      return res
    }
  • 手写bind 在其中可用到手写的newCall或newApply
复制代码
  var newBind=function(obj){
      var _this=this
      var arr1=Array.prototype.slice.newCall(arguments,1)
      //在此可能或获取到一部分参数

      var newFunc=function(){
        // 在此也可获取到一部分参数
        var arr2=Array.prototype.slice.newCall(arguments)
        var list=arr1.concat(arr2)
        if(this instanceof newFunc){
          return _this.newApply(this,list)// 返回的函数可以作为构造函数使用,实现作为构造函数时,this就失效了
        }else{
          return _this.newApply(obj,list)
        }
      }
      return newFunc
    }
复制代码

 

posted @   南无、  阅读(19)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
点击右上角即可分享
微信分享提示