前端必须理解this的相关知识

2022-03-07 14:43:31 浏览数 (1)

一、对this的产生原因分析和了解

代码语言:javascript复制
1.this指的是函数运行时所在的环境(即调用的对象)。
2.JavaScript 语言之所以有this的设计,跟内存里面的数据结构有关系

二、this绑定详解

this 实际上是在函数被调用时发生的绑定,它指向什么地方完全取决于函数在哪里被调用。

1.默认绑定

代码语言:javascript复制
    function foo(){
        var a = 1 ; //局部变量
        console.log(this.a);   
    }
    var a = 10;  //全局变量
    foo(); //window.foo()

2.隐性绑定

代码语言:javascript复制
var a = 10;  //全局变量
function foo(){
    var a = 1 ; //局部变量
    console.log(this.a);   
}
var obj = {
    a : 20,
    foo : foo
}
obj.foo(); //window.obj.foo() 

3.显示绑定apply,call,bind 这个三个函数都是改变this指向

代码语言:javascript复制
    (1)call
  
    var box=document.getElementById('box')
    
    box.onclick = function(){
        console.log(this)  //指向box元素
      function boxFn(params1,params2,params3){
          console.log(this) 
      }
        boxFn() 
        boxFn.call(this,1,2,3) //call改变this指向,将this指向box元素
    }
代码语言:javascript复制
    (2)apply

    var applayObj1={
        name:'张三'
    }
    
    var applayObj={
        name:'李四',
        applayFun(param1,param2,param3){
          console.log(this.name)
        }
    }
    
    var applayfun2=applayObj.applayFun
    
    applayObj.applayFun() //window.applayObj.applayFun()
    
    applayfun2.apply(this,[1,2,3]) //window.applayfun2.apply(this,[1,2,3])
    
    applayfun2.apply(applayObj1,[1,2,3]) //window.applayfun2.apply(applayObj1,[1,2,3])
代码语言:javascript复制
    (3)bind
    
    var title='全局title'
    var applayObj1={
      name:'张三'
    }
    
    var bindObj={
      title:'改变this',
      bindFun(){
        console.log(this)
      }
    }
    
    bindObj.bindFun()
    
    var aa=bindObj.bindFun
    
    aa()
    
    aa.bind(applayObj1)()

4.new 绑定

new出来的对象有以下新特性:

代码语言:javascript复制
(1)创建一个新对象。
(2)把这个新对象的__proto__属性指向 原函数的prototype属性。(即继承原函数的原型)
(3)将构造函数的作用域赋给新对象(因此 this 就指向了这个新对象)
(4)返回新对象。(底层运行机制return返回一个新对象)
代码语言:javascript复制
   var blogA='123'
   function blog(){
       this.blogA='456'
       this.blogFn=function(){
           console.log(this.blogA)
       }
   }
   var newblogObj=new blog() 

   newblogObj.blogFn()
   
   console.log(newblogObj)

三、箭头函数的this绑定

(1)函数体内的this对象,就是定义时所在的对象,而不是使用时所在的对象。

代码语言:javascript复制
    var a=12
    function foo(){    
        this.a=13
        return ()=>{
          console.log(this.a)
        }
    }
    let newFoo=new foo()   
    newFoo() 
    

    var b='666'    
    function foo2(){
        console.log(this)
        return ()=>{
            console.log(this.b)
        }
    }    
    var baz=foo2()
    baz();  

(2)箭头函数可以让setTimeout里面的this,绑定定义时所在的作用域,而不是指向运行时所在的作用域

代码语言:javascript复制
  function Timer() {
      this.s1 = 0;
      this.s2 = 0;
      
      console.log(this)
      
      // 箭头函数
      setInterval(() => this.s1  , 1000); //箭头函数没有this,它的this来自绑定时所在的作用域 即外部代码块的this
      
      
      // 普通函数
      setInterval(function () { 
        this.s2  ; //this为window
      }, 1000);
      
      
    }

    var timer = new Timer();
    
    setTimeout(() => console.log('s1: ', timer.s1), 3100)
    
    setTimeout(() => console.log('s2: ', timer.s2), 3100)
代码语言:javascript复制
(3). 箭头函数this不可修改
代码语言:javascript复制
    var obj = {
      b : 999
   }
  var b='666'    
  function foo2(){
      console.log(this)
      return ()=>{
        console.log(this.b)
      }
  }    
  var baz=foo2()
  
  baz();  
  
  baz.call(obj)

四、this指向与继承

代码语言:javascript复制
//示例
        function Parent (name,sex){
            this.name = name;
            this.sex  = sex;
        }

        //添加原型方法
        Parent.prototype.show = function(){
        
            console.log("姓名:"   this.name   "性别"   this.sex)
    
        }
        
        //声明函数继承 Parent的函数 并添加自己的函数
         function Worker(name,sex,job){
         
            //通过call方法改变Parent的this指向
            console.log(this)
            Parent.call(this,name,sex)
            this.job = job;
            
         }

        //此时wk里既有Parent的函数属性 又有了Worker函数的属性
         Worker.prototype=Parent.prototype
         
         var wk = new Worker("小明","男","程序员")
         
         console.log(wk.name);
         
         console.log(wk.sex);
         
         console.log(wk.job);
         
         wk.show()

0 人点赞