this指向

this指向思维导图

在这里插入图片描述

this指向问题重要!!!重要!!!重要!!!

1.this是个关键字,在作用域内使用的关键字

  • 要么使用在全局作用域
  • 要么使用在私有作用域
    因为只有函数生成私有作用域,所以就是使用在函数内部

2.this在全局作用域使用的时候

  • 表示的意义就是window, 也叫作全局

  • 一般不会在全局作用域下直接使用this

    //全局作用域使用this
    console. log( this)
    console. log(window)
    console. log(window === this)
    

    控制台输出:
    在这里插入图片描述

3.this在**私有作用域(函数)**使用的时候

  • 不管函数怎么定义,不管函数在哪定义,只看函数怎么调用(箭头函数除外)

  • 普通调用/直接调用
    函数名() 这样调用函数的时候
    this 就是window

  • 对象调用
    对象名.函数名() 这样调用函数的时候
    对象名['函数名']() 这样调用函数的时候
    this就是前面的对象,点前面是谁就是谁

      fn函数调用 里面的this 就是obj
      obj.fn()
      obj['fn']()
    
  • 定时器处理困数
    setTimeout(函数, 时间)
    setInterval(函数,时间)
    this 就是window

  • 事件处理函数
    事件源.on事件类型=事件处理函数
    事件源. addEventListener(‘事件类型’, 事件处理函数)
    this 就是事件源(绑定在谁身上的事件)

    //私有作用域使用this
    //这个丽数只要调用,就会在控制台打印this
    function fn() {
    	console.log( this )
    }
    //调用fn兩数
    //直按调用
    fn() //本次调用,因为是直接调用,两数内部的this 就是wi ndow
    //对象调用
    var obj ={
    	name:'Jack',
    	//把fn存储的丽数地址给了obj对象的f成员份
    	//从此以后,obj.f和全局变量fn指向同个丽数空间
    	//两个名字调用的是同个两数
    	f: fn
    }
    obj.f() //本次调用,因为是对象调用,函数内部的this 就是这个对象obj
    

    控制台输出:
    在这里插入图片描述

<!-- css样式 -->
div{
	width:200px;
	height:200px:
	background:pink;
}
<!--html -->
<div> </div>

<!-- js -->
<script>
	//事件处理函数
	var div = document . querySelector( 'div')
	//当你点击div的时候,执行fn函数
	//此时是把fn函数当做事件处理函数使用
	div.onclick = fn //本次调用,因为是事件处理函数调用,函数内部的this 指向事件源,也就是div
	//点击div区域,控制台输出div
	
	//定时器处理函数
	//会在1000ms 以后调用fn函数
	//此时是把fn函数当做定时器处理函数使用
	setTimeout(fn, 1000) //本次调用,因为是定时器处理函数调用,丙数内部的this 指向window
</script>

【练习】

function fn() 
	function fun() {
	//这个this是书写在fun私有作用域的this
	//只看fun函数是怎么被调用的
	//不需要管fn是怎么调用的,只看fun这个函数是怎么调用的就可以了
	console.log( this )
	//普通调用的方式调用了fun函数
	// fun函数内部的this -> window
	fun( )
}
varobj={
	name :	'我是obj对象',
	f: fn
}
// 开始调用
obj.f( )

总结:

普通函数的this指向
      声明式 赋值式 定时器 延时器 forEach 
          window
      事件处理函数
          事件源

      数组/对象中的函数
          存储函数的数组/对象

  箭头函数的this指向
      父级程序的this指向
          没有父级程序 父级程序没有this 
              this是 window

  改变this指向
      箭头函数不能改变this指向 永远是父级程序的this指向

      执行时改变
          函数.call(新的this指向 , 原始函数的实参)

          函数.apply(新的this指向 , [原始函数的实参])

      生成有一个新的函数
          const 变量 = 函数.bind( 新的this指向 , 原始函数的实参 ) 

强行改变this 指向

  • 在私有作用域内,当函数调用的时候,有本身的this 指向
  • 我们可以使用一些方法来修改函数内的this指向
  • 在JS内修改this 指向有三个方法
    1. call( )
    2. apply( )
    3. bind( )
  1. call()方法

    • 使用方式:
      函数名.call( )
      对象名.函数名.call( )

    • 注意:
      不要再事件处理函数和定时器处理函数里面使用
      会立即调用函数

    • 参数:
      第一个:表示函数内的this 指向
      第二个开始:表示传递给函数的实参

      // 1. call()
      function fn(a, b) {
      	console.group('函数fn内的打印' )
      	console.log('a ':, a)
      	console.log('b ':, b)
      	console.log( 'this:', this)
      	console.groupEnd( )
      }
      //普通调用方式
      //本次调用是普通调用方式,this -> window
      // 10是传递给a形参的内容
      // 20是传递给b形参的内容
      fn(10, 20)
      
      //当你需要修改本次函数内的 this 指向的时候
      var arr = ['hello', 'world']
      //也是在立即调用fn函数
      //本次调用的时候,使用了call 把 fn 函数内的 this 强行修改成了arr
      // 100是传递纷a形参的内容
      // 200是传递给b形参的内容
      fn.call( arr,100200)
      
      

    // var obj = { name: ‘Jack’, age: 18 }
    // 本次调用的时候,使用call 把fn函数内的 this强行修改成 了obj
    // 1000 是传递给a形参的内容
    // 2000是传递给b形参的内容
    // fn.call(obj, 1000, 2000)

     // 假设我想修改 this指向,我是用了call 方法
     //调用fn函数,使用calZ方法, 把fn雨数内的this 修改为了arr
     // '你好’是传递给 a 形参的内容
     // '世界'是传递给 b 形参的内容
     //相当于你在书写的时候,就把函数调用了 ,等到1000ms 以后,没有内容来执行了
     //就是fn和fn()的区别
     setTimeout(fn.call(arr, ' 你好','世界'),1000)
     
     // 1000ms 以后执行fn函数
     setTimeout(fn, 1000 )
     // 1000ms 以后执行fn函数的返回值
     // setTimeout(fn(), 1000)
     var res=fn()
     setTimeout(res,1000)
     ```
     控制台输出内容:
     ![在这里插入图片描述](https://img-blog.csdnimg.cn/20210709173918858.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2VzdHJ1c0tpbmc=,size_16,color_FFFFFF,t_70)
     ![在这里插入图片描述](https://img-blog.csdnimg.cn/20210709175505140.png)
    
  2. apply()方法

    • 使用方式:
      函数名.apply()
      对象名.函数名.apply()

    • 注意:
      不要在事件处理函数和定时器处理函数时候使用
      会立即调用函数

    • 参数:
      第一个:表示函数内的this 指向
      第二个:是一个数组或者伪数组都行,里面的每一项是给函数传递的参数

    • 特殊的使用方式:
      改变一个函数的传递参数的方式

      // 2. apply()
      function fn(a, b) {
      	console.group('函数fn内的打印' )
      	console.log('a ':, a)
      	console.log('b ':, b)
      	console.log( 'this:', this)
      	console.groupEnd( )
      }
      
      var arr = ['hello', 'world']
      
       var obj = { name: 'Jack', age: 18 }
      
      //普通调用
      fn(10, 20)
      
      //使用apply修改this指向
      //本次调用的时候,使用apply 方法来进行调用的
      // arr就是本次调用的时候,函数内的this指向
      // [100, 200]是给fn传递参数使用的
      //数组[0]也就是100是给a形参的内容
      //数组[1]也就是200是给b形参的内容
      fn.apply(arr, [100, 200])
      
      //本次调用的挥手,使用apply 方法来进行调用的
      // obj就是本次调用的时候,函数内的this指向
      // [1000, 2000] 是给fn传递参数使用的
      //数组[0]也就是1000是给a形参的内容
      //数组[1]也就是2000 是给b形参的内容
      fn. apply(obj, [1000, 2000])
      
      
      //在定时器处理函数里面
      //因为apply会立即调用函数
      //那么就是在你书写的时候, 就已经把函数调用了,1000ms 以后就没有函数执行才
      setTimeout(fn. apply(obj, ['你好''世界']), 1000)
      

      控制台输出内容:
      在这里插入图片描述

      // apply方法的特殊使用方式
      //改变一个函数的传递参数的方式
      //例子: Math.max() 方法
      /*
      	在JS内有一个叫做Math 的对象
      		=>	里面有一个叫做max的成员,是一个函数
      	Math = {
      		max: function () {}
      	}
      	
      	语法:
      		=> Math.max(数字1, 数字2, 数字3,...) 
      */
      //本身
      //注意:需要一个一个的传递参数, 判断多个参数内的最大值
      var res = Math.max(10, 20, 30, 40, 3323)
      console.log(res)
      
      
      
      //需求:判断数组里面的最大值
      //就可以使用apply 方法来进行参数传递方式的改变
      var a = [10,20,33,23,14,51,32]
      
      //var r2 = Math. max(a)
      //console.log(r2)    //控制台输出 null
      
      //因为这次调用不是为了让你修改this 指向
      //而是为了使用apply的传递给函数参数的方式
      //此时a就是传递给Math. max函数的参数
      // a[0]就是第一个参数
      // a[1]就是第二个参数
      var r2 = Math. max. apply(null, a)
      console.log(r2)
      

      控制台输出内容:
      在这里插入图片描述

  3. bind()方法

    • 使用方式:
      函数名.bind()
      对象名.函数名.bind()

    • 注意:
      可以使用在定时器处理函数或者事件处理函数里面
      不会立即调用函数
      而是给一个返回值,返回一个新的函数

    • 参数:
      第一个:表示函数内的this 指向
      第二个开始:表示传递给函数的实参
      另一种,在使用bind 的时候,只传递一个参数,就是修改this 指向
      当你调用返回值新函数的时候,在传递需要的实参

    • 返回值:
      是一个新的函数,把原始函数复制了一份一模一样的,只不过把里面的this锁定好了
      不会立即调用函数

      // 3.bind()
      function fn(a, b) {
      	console.group('函数fn内的打印' )
      	console.log('a ':, a)
      	console.log('b ':, b)
      	console.log( 'this:', this)
      	console.groupEnd( )
      }
      
      var arr = ['hello', 'world']
      
       var obj = { name: 'Jack', age: 18 }
       
       console.log('fn : ',fn)
      //普通调用
      // fn(10, 20)
      
      //使用bind 修改this 指向
      //注意:本次没有调用fn函数
      // bind的作用只是复制了一份fn函数
      //把复制的这份fn函数里面的this锁定为了obj
      // 100是传递给a形参的内容
      // 200 是传递给b形参的内容
      // 把复制好的新函数作为 I返回值
      // res接受的就是一个锁定好了this指向的新函数
      var res	= fn.bind(obj, 100200 )
      console.log( 'res :' , res )
      //当你调用res的时候,res 里面的this 就是obj 了
      res( )
      // t经被锁死的this指向,还能不能通过call 再次修改?
      res.call(arr) 
      
      	// bind的作用只是复制了一份fn函数
      	//把复制的这份fn函数里面的this锁定为了arr
      	// 1000 是传递给a形参的内容
      	// 2000 是传递给b形参的内容
      	//把复制好的新函数作为了返回值
      	// r2接受的就是一个锁定好了this指向的新函数
      	var r2 = fn.bind(arr, 10002000 )
      	r2( )
      

      控制台输出内容:在这里插入图片描述
      在这里插入图片描述

      在这里插入图片描述
      参数另一种

      // bind的作用只是复制了一份fn函数
      //把复制的这份fn函数里面的this 锁定为了arr 
      //使用bind的时候,只是锁定this, 不锁定形参
      //把复制好的新函数作为了返回值
      // r2接受的就是个锁定好 了this指向的新函 数
      var r2 = fn. bind( arr)
      //将来调用的时候,this 是锁定好的,形参可以根据需求来实时填入
      r2( '你好''世界')
      r2( ' hello', 'world')
      

      控制台输出内容:
      在这里插入图片描述

      //问题:如果我使用bind的时候,和调用返回值函数的时候都传递了实参,哪一个是真实的?
      //因为bind就是在锁定一系列内容,this和形参
      //如果你在使用bind的时候,就给该函数传递I内容,那么参数值就被锁定了
      //本次的调用-共锁定了三个内容
      //      fn函数内的this 被锁定为了obj
      //      fn函数的a形参的值被锁定为了”你好'
      //      fn函数的b形参的值被锁定为了'世界’
      var res = fn.bind(obj, '你好''世界')
      res( )
      //锁定以后,形参就不能再被修改了
      res( 'hello', 'world' )
      //锁定以后,this 也不能再被修改了
      res. call(arr)
      
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

半生过往

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值