当前位置: 首页 > article >正文

JavaScript函数中this的指向

总结:谁调用我,我就指向谁(es6箭头函数不算)

一、ES6之前

  • 每一个函数内部都有一个关键字是 this ,可以直接使用

  • 重点: 函数内部的 this 只和函数的调用方式有关系,和函数的定义方式没有关系

1、 函数内部的 this 指向谁,取决于函数的调用方式

1.1、全局定义的函数直接调用,this => window
 function fn() {
   console.log(this)
 }
 fn()
 // 此时 this 指向 window
1.2、 对象内部的方法调用,this => 调用者
var obj = {
  fn: function () {
    console.log(this)
  }
}
obj.fn()
// 此时 this 指向 obj
1.3、 定时器的处理函数,this => window
setTimeout(function () {
  console.log(this)
}, 0)
// 此时定时器处理函数里面的 this 指向 window
1.4、事件处理函数,this => 事件源
div.onclick = function () {
  console.log(this)
}
// 当你点击 div 的时候,this 指向 div
1.5、自调用函数,this => window
(function () {
  console.log(this)
})()
// 此时 this 指向 window
1.6 函数嵌套场景分析
  • 成员函数嵌套this继承一定会出问题
 <script>
     // "use strict";
     function A() {
         console.log("A",this)
         function B(){
             console.log("B", this);
         }
         B();
     }

     A();

     var o = {             // 对象o
         m: function() {      //对象的方法m
             console.log(this);
             f();                   //调用嵌套函数
             function f() {         //嵌套函数f
                 console.log(this);
             }
         }
     }
     o.m();
 </script>

非严格模式,打印结果如下
在这里插入图片描述
对于类中成员函数嵌套的情况,考虑使用箭头函数,这样this就不会乱,一直都是对象。

2、改变this指向

call 和 apply 和 bind

  • 刚才我们说过的都是函数的基本调用方式里面的 this 指向
  • 我们还有三个可以忽略函数本身的 this 指向转而指向别的地方
  • 这三个方法就是 call / apply / bind
  • 是强行改变 this 指向的方法
call
  • call 方法是附加在函数调用后面使用,可以忽略函数本身的 this 指向

  • 语法: 函数名.call(要改变的 this 指向,要给函数传递的参数1,要给函数传递的参数2, ...)

    var obj = { name: 'Jack' }
    function fn(a, b) {
      console.log(this)
      console.log(a)
      console.log(b)
    }
    fn(1, 2)
    fn.call(obj, 1, 2)
    
    • fn() 的时候,函数内部的 this 指向 window
    • fn.call(obj, 1, 2) 的时候,函数内部的 this 就指向了 obj 这个对象
    • 使用 call 方法的时候
      • 会立即执行函数
      • 第一个参数是你要改变的函数内部的 this 指向
      • 第二个参数开始,依次是向函数传递参数
apply
  • apply 方法是附加在函数调用后面使用,可以忽略函数本身的 this 指向

  • 语法: 函数名.apply(要改变的 this 指向,[要给函数传递的参数1, 要给函数传递的参数2, ...])

    var obj = { name: 'Jack' }
    function fn(a, b) {
      console.log(this)
      console.log(a)
      console.log(b)
    }
    fn(1, 2)
    fn.apply(obj, [1, 2])
    
    • fn() 的时候,函数内部的 this 指向 window
    • fn.apply(obj, [1, 2]) 的时候,函数内部的 this 就指向了 obj 这个对象
    • 使用 apply 方法的时候
      • 会立即执行函数
      • 第一个参数是你要改变的函数内部的 this 指向
      • 第二个参数是一个 数组,数组里面的每一项依次是向函数传递的参数
bind
  • bind 方法是附加在函数调用后面使用,可以忽略函数本身的 this 指向

  • 和 call / apply 有一些不一样,就是不会立即执行函数,而是返回一个已经改变了 this 指向的函数

  • 语法: var newFn = 函数名.bind(要改变的 this 指向); newFn(传递参数)

    var obj = { name: 'Jack' }
    function fn(a, b) {
      console.log(this)
      console.log(a)
      console.log(b)
    }
    fn(1, 2)
    var newFn = fn.bind(obj)
    newFn(1, 2)
    
    • bind 调用的时候,不会执行 fn 这个函数,而是返回一个新的函数
    • 这个新的函数就是一个改变了 this 指向以后的 fn 函数
    • fn(1, 2) 的时候 this 指向 window
    • newFn(1, 2) 的时候执行的是一个和 fn 一摸一样的函数,只不过里面的 this 指向改成了 obj
方法this 指向参数传递方式执行时机
call指定逐个传递立即执行
apply指定数组形式传递立即执行
bind指定逐个传递(可选)返回新函数,需手动调用

二、ES6之后的箭头函数

箭头函数内部没有 this,箭头函数的 this 是上下文的 this

const input = document.getElementById('input');
const btn = document.getElementById('btn');
		
 const obj = {
	    value: 'Hello',
	    printWithRegularFunction: function() {
	      setTimeout(function() {
	        console.log('普通函数:', this.value); // 这里的 this 指向全局对象(window)
	      }, 1000);
	    },
	    printWithArrowFunction: function() {
	      setTimeout(() => {
	        console.log('箭头函数:', this.value); // 这里的 this 指向 obj 对象
	      }, 1000);
	    }
  };
	
btn.addEventListener('click', () => {
    obj.value = input.value; // 将输入框的值赋值给 obj.value
    obj.printWithRegularFunction();
    obj.printWithArrowFunction();
 });

运行结果 在这里插入图片描述

注意对象中的箭头函数

虽然箭头函数不能用于定义对象方法(因为它没有自己的 this),但可以在对象中定义箭头函数作为普通属性。

const obj = {
  name: 'Alice',
  sayHello: () => {
    console.log(`Hello, ${this.name}`); // 这里的 this 指向外层作用域
  }
};

obj.sayHello(); // Hello, undefined

注意:箭头函数不适合用于对象方法,因为它会丢失对对象 this 的绑定。尽管我们可能在方法中不使用this,且不访问其他成员属性。但是,一般当我们使用对象调用此方法时是希望它指向obj的,这违背了我们的本意。


http://www.kler.cn/a/527674.html

相关文章:

  • 【回溯+剪枝】组合问题!
  • 【React】PureComponent 和 Component 的区别
  • C语言指针专题四 -- 多级指针
  • 绝对值线性化
  • CF 761A.Dasha and Stairs(Java实现)
  • AI 的安全性与合规性:实践中的最佳安全策略
  • python 文件操作全知道 | python 小知识
  • 36. printf
  • 团体程序设计天梯赛-练习集——L1-029 是不是太胖了
  • 大模型高频知识汇总:查漏补缺参考大全
  • 【Redis】set 和 zset 类型的介绍和常用命令
  • oracl:多表查询>>表连接[内连接,外连接,交叉连接,自连接,自然连接,等值连接和不等值连接]
  • Docker小游戏 | 使用Docker部署跳一跳经典小游戏
  • 23.Word:小王-制作公司战略规划文档❗【5】
  • Python3 + Qt5:实现AJAX异步更新UI
  • EtherCAT主站IGH-- 25 -- IGH之fsm_slave_scan.h/c文件解析
  • DeepSeek 使用初体验
  • Git的安装步骤详解(复杂的安装界面该如何勾选?)
  • 在线知识库创建与维护提升企业效率与知识共享能力
  • 【Unity3D】实现横版2D游戏角色二段跳、蹬墙跳、扶墙下滑
  • Linux Vim编辑器:快捷键与高效编辑技巧
  • C语言指针专题一 -- 指针基础原理
  • 【Linux】使用管道实现一个简易版本的进程池
  • Pandas 常用函数
  • 【PLL】杂散生成和调制
  • (动态规划基础 打家劫舍)leetcode 198