this 指向 及 改变 _ 笔记版

30 篇文章 0 订阅
10 篇文章 0 订阅
本文详细介绍了JavaScript中this关键字的用法,包括在普通调用、对象调用、定时器处理函数、事件处理函数、自执行函数、箭头函数和构造函数中的不同指向。此外,还讲解了如何通过call()、apply()和bind()方法强行改变this指向,并通过实际示例展示了它们的特殊作用。最后,文章通过一个this图例总结了this的关键概念。
摘要由CSDN通过智能技术生成

目录

函数内使用 this 关键字 : 

1. 普通调用(全局调用) :

2. 对象调用 : 

3. 定时器处理函数 : 

4. 事件处理函数 : 

5. 自执行函数 : 

6. 箭头函数 : 

7. 构造函数 : 

 强行改变 this 指向 : 

1. call( )

2. apply( )

 apply 的 特殊作用 :

3. bind( )

 bind 的 特殊作用 :

this 图例 :


this 是一个 关键字

是一个 使用在 作用域内的 关键字

=> 要么使用在全局

~> this 就是 Window

=> 要么使用在函数内部

~> this 表示的是该函数的 context (执行上下文)

// 0. 全局使用 this
console.log(this)
console.log(window)
console.log(window === this)  // true

函数内使用 this 关键字 : 

概念 : + **函数内的 this , 和函数的定义方式没有关系, 和函数在哪定义没有关系,

        => 只看函数怎么调用 (箭头函数除外) **

+ 几种调用方式, 决定不同的 this 指向 : 

1. 普通调用(全局调用) :

=> 书写: 函数名( )
=> 该函数内的 this 指向 Window 

// 1. 普通调用
  function fn() {
    console.log('我是全局 fn 函数')
    console.log(this)
    console.log('------fn 函数结束------')
  }
// 标准的 普通调用
// fn 这个函数内的 this => Window
  fn()

2. 对象调用 : 

=> 书写 : 对象名.函数名( )

  ~> 对象名['函数名']( )

  ~> 数组[索引]( )

=> 书写: xxx.函数名( )

=> 该函数内的 this 指向  前面的内容

  ~> 也就是那个对象或者数组

// 2. 对象调用
    var obj = {
      name: '我是 obj 对象',
      fn: function () {
        console.log('obj 内的 fn 函数')
        console.log(this)	// Object
        console.log('------fn 函数结束------')
      }
    }
// 标准的 对象调用
// 函数内的 this => obj
    obj.fn()
// 同一个函数, 不同的调用方式, 决定了函数内的 this 指向不一样
    function fn() {
      console.log('fn 函数')
      console.log(this)		
      console.log('------fn 函数结束------')
    }

    var obj = {
      name: '我是 obj 函数',
      // 把 fn 存储的函数地址, 赋值给了 obj 内的 f 成员
      f: fn
    }
// 从此以后, 全局 fn 变量和 obj 内的 f 成员调用的是一个函数
// 调用全局的 fn 函数, 调用方式: 普通调用
  // fn()	// this => Window
// 调用全局的 fn 函数, 调用方式: 对象调用
    obj.f()	// this => Object

3. 定时器处理函数 : 

=> 书写 :
  ~> setTimeout(函数, 数字)
  ~> setInterval(函数, 时间)
=> 该函数内的 this 指向 Window 

function fn() {
      console.log('我是全局 fn 函数')
      console.log(this)    // this => Window
      console.log('------fn 函数结束------')
    }
// 3. 定时器处理函数
// 1000ms 以后执行的是 fn 函数
// 在这里把 fn 函数当做定时器处理函数来使用了
    setTimeout(fn, 1000)

4. 事件处理函数 : 

=> 书写 :

~> 事件源.on事件类型 = 事件处理函数

~> 事件源.addEventListener('事件类型', 事件处理函数)

=> 该函数内的  this  指向  事件源  (谁身上的事件)

function fn() {
      console.log('我是全局 fn 函数')
      console.log(this)    // this => div
      console.log('------fn 函数结束------')
    }
// 4. 事件处理函数
    var box = document.querySelector('div')
// 当你点击 box 元素的时候, 执行 fn 函数
// 此时, 把 fn 函数当做事件处理函数使用了
    box.onclick = fn

5. 自执行函数 : 

=> (function ( ) { })( )

  ~function ( ) { }( )

  !function ( ) { }( )

=> 该函数内的 this 指向 window 

// 5. 自执行函数
(function () {
      console.log(this)   // Window
    })()

6. 箭头函数 : 

=>  this  ~>  上下文  (外部函数的 this)


7. 构造函数 : 

书写 :

=> new 函数名( )

=>  this   ~>   当前实例  (构造函数自动创造出来的那个对象)

构造函数内的 this 指向当前实例


 强行改变 this 指向 : 

+ 不管你本身指向什么位置, 我让你指向哪, 你就得指向哪

function fn(a, b) {
      console.group('fn 函数内的 打印')
      console.log('this : ', this)
      console.log('a : ', a)
      console.log('b : ', b)
      console.groupEnd()
    }
// 0. 普通调用
// 因为是 普通调用
// this => window
// a => 10
// b => 20
    fn(10, 20)

 


1. call( )

        + 语法: 跟随在函数名后面调用

          => 函数名.call( )

          => 对象名.函数名.call( )

        + 意义: 修改 函数内 的 this 指向

        + 参数:

          => 第一个参数 : 要修改的函数内的 this 指向

          => 第二个参数开始 : 依次给函数内每一个形参传递实参

        + 特点: 立即调用函数

        + 用处:

          => 在立即执行的函数时才使用

          => 事件处理函数, 和 定时器处理函数, 一般不会使用这个方法 

function fn(a, b) {
      console.group('fn 函数内的 打印')
      console.log('this : ', this)
      console.log('a : ', a)
      console.log('b : ', b)
      console.groupEnd()
    }
    var obj = {
      name: '我是 obj 对象'
    }
// 因为是 利用 call 调用
// obj 就是 fn 函数内的 this 指向, fn 这个函数内的 this 就是 obj
// 100 就是给 fn 函数的第一个实参, 赋值给了形参 a
// 200 就是给 fn 函数的第二个实参, 赋值给了形参 b
    fn.call(obj, 100, 200)    // a : 100   b : 200

function fn(a, b) {
      console.group('fn 函数内的 打印')
      console.log('this : ', this)
      console.log('a : ', a)    // a: 1000
      console.log('b : ', b)    // b: 2000
      console.groupEnd()
    }
    var arr = [ 100, 200, 300, 400, 500 ]
// 因为是 利用 call 调用 , 并且传递的第一个参数是 arr
// 就是在立即调用 fn 函数的同时, 把 fn 函数内的 this 指向了 arr
// 从第二个参数开始, 1000 赋值给了第一个形参 a
// 2000 赋值给了 第二个形参 b
    fn.call(arr, 1000, 2000)    // a = 1000  b = 2000


2. apply( )

        + 语法: 跟随在函数名后面调用

          => 函数名.apply( )

          => 对象名.函数名.apply( )

        + 意义: 修改 函数内 的 this 指向

        + 参数:

          => 第一个参数: 要修改的函数内的 this 指向

          => 第二个参数: 是一个数组或者伪数组都行

            -> 数组或者伪数组内的每一项依次给函数传递实参

        + 特点 : 立即调用函数

        + 用处:

          => 在立即执行的函数时才使用

          => 事件处理函数, 和 定时器处理函数, 一般不会使用这个方法

        + 特殊作用: 改变给函数传递参数的方式

function fn(a, b) {
      console.group('fn 函数内的 打印')
      console.log('this : ', this)
      console.log('a : ', a)    // a: 100
      console.log('b : ', b)    // b: 200
      console.groupEnd()
    }
    var obj = {
      name: '我是 obj 对象'
    }
// 因为是 利用 apply 调用函数 fn
// 所以 把函数内部的 this 改变成为 obj
// obj 就是 fn 函数内的 this 指向
// 第二个参数传递了一个数组
// 数组中的 [0] 是给 fn 函数的第一个实参, 赋值给了形参 a
// 数组中的 [1] 是给 fn 函数的第二个实参, 赋值给了形参 b
    fn.apply(obj, [100, 200])

 apply 的 特殊作用 :

var arr = [10, 20, 18, 32, -10, 21, 19]
// 我想求 arr 内的最大值
// 利用 apply 方法来改变 给函数传递参数的方式
// apply 第二个参数是一个 数组 或者 伪数组, 里面的内容依次给函数的实参
// null 就是 Math.max 函数内的 this 指向
// arr[0] 就是 Math.max 的第一个实参
// arr[1] 就是 Math.max 的第二个实参
// ...
    var res = Math.max.apply(null, arr)
    console.log(res)    // 32

3. bind( )

+ 语法: 跟随在函数名后面调用

          => 函数名.bind( )

          => 对象名.函数名.bind( )

        + 意义: 修改 函数内 的 this 指向

        + 参数:

          => 第一个参数: 要修改的函数内的 this 指向

          => 第二个参数开始: 依次给函数内每一个形参传递实参

        + 特点:

          => 不会立即调用函数 , 而是返回一个新的函数给你

          => 一个被改变了 this 指向的新函数

        + 用处:

          => 在非立即调用的函数时使用

          => 因为他不会立即调用函数, 而是返回一个改变好 this 指向的函数

        + 特殊作用 : 改变一些不会立即执行的函数内的 this 指向

function fn(a, b) {
      console.group('fn 函数内的 打印')
      console.log('this : ', this)
      console.log('a : ', a)
      console.log('b : ', b)
      console.groupEnd()
    }
    var obj = {
      name: '我是 obj 对象'
    }
// 利用 bind 调用了 fn 函数, 把函数内的 this 改变成为了 obj
// obj 就是 fn 函数内的 this 指向
// 100 赋值给形参 a
// 200 赋值给形参 b
// 注意: 因为是 bind, 不会把 fn 函数执行, 而是把 fn 函数复制了一份, 把内部的 this 锁定为 obj
// res 接受的就是 bind 方法复制出来的 fn 函数, 和 fn 函数一模一样, 但是 res 函数内的 this 是 obj
    var res = fn.bind(obj, 100, 200)
    console.log('fn : ', fn)
    console.log('res : ', res)
    res()

 

 bind 的 特殊作用 :

需求: 想把定时器处理函数内的 this 指向 obj

function fn(a, b) {
      console.group('fn 函数内的 打印')
      console.log('this : ', this)
      console.log('a : ', a)
      console.log('b : ', b)
      console.groupEnd()
    }
// 1000ms 以后执行 fn 函数
// 因为 fn 函数被当做了 定时器处理函数 使用, 所以 fn 内的 this 指向 window
    setTimeout(fn, 1000)

方案 1 : 利用 call / apply

function fn(a, b) {
      console.group('fn 函数内的 打印')
      console.log('this : ', this)
      console.log('a : ', a)
      console.log('b : ', b)
      console.groupEnd()
    }

    var obj = {
      name: '我是 obj 对象'
    }
// 方案1: 利用 call/apply
// 因为 call 和 apply 会立即调用函数, 当你设置这个定时器的时候, 已经把 fn 函数调用了
// 等到 1000ms 以后, 就没有函数执行了
    setTimeout(fn.call(obj, 100, 200), 1000)

 

 方案2: 利用 bind

function fn(a, b) {
      console.group('fn 函数内的 打印')
      console.log('this : ', this)
      console.log('a : ', a)
      console.log('b : ', b)
      console.groupEnd()
    }

    var obj = {
      name: '我是 obj 对象'
    }
// 方案2: 利用 bind
// 因为 bind 不会立即调用函数, 而是返回一个一模一样的函数, 只是被锁定了 this
// 你调用 res 和 调用 fn 是一模一样的代码, 只是 this 不一样
    var res = fn.bind(obj, 1000, 2000)
// 把 res 当做定时器处理函数, 在 1000ms 后执行
// 1000ms 以后执行的是一个 和 fn 函数一模一样的函数, 只是 this 指向了 obj
    setTimeout(res, 1000)


this 图例 :

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值