JavaScript this 关键字的多场景指向与 call/apply/bind 用法详解

作者:异步漫步时间:2026-10-31 21:37:36浏览:357

本文详解 JavaScript 中 this 关键字在不同执行环境下的指向规则,包括全局、函数调用、事件处理、对象方法及箭头函数等场景。重点解析 call、apply 和 bind 三个改变 this 指向的方法及其参数传递差异,帮助开发者准确掌握函数上下文绑定技巧。

this 的概念定义

作为 JavaScript 的关键字,this 代表函数执行时自动创建的内部对象,仅限在函数体内访问。其具体值取决于函数的调用方式,但遵循核心规则:this 指向实际调用该函数的对象。

this 的多重指向场景

1. 全局作用域下的 this

处于全局作用域时,this 指向全局对象,在浏览器环境中即为 window 对象:

var name = 'name1';
console.log(name);               // "name1"
this.name = 'name2';
console.log(name);               // "name2"
console.log(this.name);          // "name2"
window.name = 'name3';
console.log(name);               // "name3"
console.log(this.name);          // "name3"
console.log(window.name);        // "name3"

2. 普通函数调用场景

当函数以全局方式被调用时,this 指向全局对象:

// 案例1
function test() {
  this.x = 1;
  alert(this.x);  // 1
}
test();
 
// 案例2
var x = 1;
function test() {
  alert(this.x);  // 1
}
test();
 
// 案例3
var x = 1;
function test() {
  this.x = 0;
}
test();
alert(x);  // 0

3. 事件处理函数中的 this

在事件监听器或处理函数中,this 指向触发该事件的目标元素:

var btn = document.getElementById("btn");
btn.onclick = function() {
  this.value = "按钮";  // this 指向 btn 元素
}

4. HTML 属性绑定的 this

在 HTML 标签的事件属性(如 onclick)中,this 指向绑定该事件的 DOM 元素:

<button onclick="fun(this)">点击</button>
<script>
function fun(_this) {
  console.log(_this);  // 输出当前点击的 button 元素
}
</script>

5. 对象方法调用中的 this

在对象字面量定义的方法中,this 指向该对象实例:

var obj = {
  name: 'jack',
  say: function() {
    console.log('obj中的this', this.name);  // this 指向 obj
  }
}
obj.say();  // "obj中的this jack"

6. 定时器回调中的 this

在 setTimeout 或 setInterval 的回调函数中,this 默认指向 window 对象:

// 问题示例
box1.onclick = function() {
  var num = 0;
  setInterval(function() {
    num++;
    this.innerHTML = str.substring(0, num);  // this 指向 window,无法正常工作
  }, 100);
}
 
// 解决方案一:使用变量保存 this
box1.onclick = function() {
  var _this = this;  // 保存当前 this 指向
  var num = 0;
  setInterval(function() {
    num++;
    _this.innerHTML = str.substring(0, num);  // 使用保存的 this
  }, 100);
}
 
// 解决方案二:使用箭头函数
box1.onclick = function() {
  var num = 0;
  setInterval(() => {  // 箭头函数继承外部 this
    num++;
    this.innerHTML = str.substring(0, num);  // this 指向 box1
  }, 100);
}

7. 箭头函数中的 this

  • 箭头函数自身不绑定 this,而是继承定义时所在词法环境的 this 值。
  • 无论使用 call、apply 还是 bind 方法,均无法改变箭头函数的 this 指向。
var obj = {
  name: "jack",
  say: () => {
    console.log(this.name);  // this 指向全局对象,而非 obj
  }
};

8. call、apply 与 bind 方法中的 this

这三个方法属于函数对象,主要用于显式指定函数执行时的 this 指向。

8.1 call 方法详解

语法格式:fun.call(thisArg, arg1, arg2, ...)

  • 支持立即执行调用。
  • 第一个参数用于指定 this 的目标对象。
  • 后续参数以逗号分隔的形式逐个传递。
function fun2(a, b) {
  console.log(a + b);  // 30
  console.log(this);   // 指向 box1 元素
}
 
box1.onclick = function() {
  fun2.call(this, 10, 20);  // 改变 this 指向为当前元素
}

8.2 apply 方法详解

语法格式:fun.apply(thisArg, [argsArray])

  • 功能与 call 相似,区别在于参数需以数组形式传递。
  • 同样支持立即执行调用。
function fun2(a, b) {
  console.log(a + b);  // 30
  console.log(this);   // 指向 box1 元素
}
 
box1.onclick = function() {
  fun2.apply(this, [10, 20]);  // 参数以数组形式传递
}

典型应用:利用 apply 获取数组最大值。

var arr = [56, 76, 45, 34, 87, 98];
var max = Math.max.apply(null, arr);  // 98
// 等价于 ES6 的扩展运算符
var max = Math.max(...arr);  // 98

8.3 bind 方法详解

语法格式:fun.bind(thisArg, arg1, arg2, ...)

  • 不立即执行函数,而是返回一个绑定了特定 this 的新函数。
  • 新函数中的 this 被永久绑定至 bind 方法的第一个参数。
function fun() {
  console.log(this);  // 指向 box1 元素
}
 
box1.onclick = function() {
  var newFun = fun.bind(this);  // 绑定 this 指向
  newFun();  // 手动调用新函数
}

call、apply 与 bind 的核心区别

  1. 执行方式差异:

    • call 和 apply 会立即执行目标函数。
    • bind 不会立即执行,而是返回一个新函数供后续调用。
  2. 参数传递方式差异:

    • call 接收分离的参数列表:func.call(this, arg1, arg2)
    • apply 接收参数数组:func.apply(this, [arg1, arg2])
    • bind 接收分离的参数列表:func.bind(this, arg1, arg2)
  3. this 指向处理差异:

    • 三者均可改变函数内部的 this 指向。
    • 若传入的第一个参数为 null 或 undefined,在非严格模式下 this 指向 window。

本文介绍了 JavaScript 中 this 关键字的多种使用场景,更多相关内容可查阅本站往期文章或继续浏览后续章节,感谢支持!

作者最新文章