JavaScript 如何改变 this 指向

在前端开发中,很多新手刚接触JavaScript时,都会被一个叫“this指向”的问题绕得晕头转向——一会儿指这个,一会儿指那个,好像没个准数。其实this本身并不复杂,它就像一个“指向开关”,掌握了切换规则,就能轻松搞定。

this到底是啥?就像聚会里的“主角”

先举个生活化的例子:你和朋友聚会,你带了零食,朋友带了饮料,聚会的“主角”是谁,决定了大家的活动内容——主角是你的话,大家吃零食;主角是朋友的话,大家喝饮料。this就像这个“聚会主角”,它决定了代码里当前逻辑的“核心对象”,所有操作都围绕它展开。

JavaScript 如何改变 this 指向

平时写代码时,this的指向默认有个“基础规则”:在全局作用域里(比如直接写在script标签里的代码),this指向浏览器的window对象,就像聚会没指定主角时,默认以在场的所有人作为“共同核心”。比如你直接打印this,会输出整个window窗口的相关属性,就像聚会时默认聊和大家都有关的话题。

最常用的3种手动改指向方法,全是日常场景

默认指向偶尔会不符合需求,这时候就需要手动调整this的“主角身份”,最常用的有3种方法,每种都对应一个具体的开发场景:

call:一次性切换,还能带参数

假设你做了一个“学生信息展示”的功能,有个通用的showInfo函数,能显示人的姓名和年龄。如果直接调用,this会指向window,显示的是window的默认属性,没用。这时候用call就能把this切换成学生对象:

`javascript

function showInfo(school, grade) {

console.log(${this.name}今年${this.age}岁,在${school}读${grade}年级);

}

const student = {name: '小明', age: 10};

// 用call把this绑定到student,同时传入学年级参数

showInfo.call(student, '实验一小', '三年级');

// 输出:小明今年10岁,在实验一小读三年级

`

就像你带了通用的聚会小游戏,想让朋友当主角玩,就直接把游戏的主角换成朋友,还能加个“带饮料”的额外要求。

apply:参数直接传数组,适合批量数据

如果需要传递的参数很多,比如学生的多门成绩,用apply更方便,它的参数要求是数组形式:

`javascript

function showScores(...scores) {

console.log(${this.name}的成绩:${scores.join('、')});

}

const student = {name: '小红'};

// 用apply把this绑定到student,成绩以数组形式传入

showScores.apply(student, [90, 95, 88]);

// 输出:小红的成绩:90、95、88

`

好比你要给聚会带一堆零食,直接把整袋零食(数组)递给主角,不用一个个递参数。

bind:提前绑定,适合固定场景

如果想把this的指向固定下来,之后重复调用,不用每次都传参数,就用bind。比如你要做一个按钮,点击时弹出学生的信息,这时候用bind固定this,避免点击时this指向按钮:

`javascript

const student = {name: '小刚', age: 12};

function showName() {

console.log(this.name);

}

// 提前把this绑定到student,生成新函数

const showStudentName = showName.bind(student);

// 后续不管怎么调用,this都是student

showStudentName(); // 输出:小刚

// 模拟按钮点击

document.querySelector('button').addEventListener('click', showStudentName);

// 点击按钮会输出小刚,不会变成按钮的属性,完美解决场景问题

`

就像你提前和聚会的主角约定好,不管谁组织聚会,主角都是他,不会临时变卦。

避开常见坑:别让this“跑错场子”

新手最容易踩的坑,就是在定时器里用this。比如你想在3秒后输出学生的名字,写了这样的代码:

`javascript

const student = {name: '小丽'};

function showName() {

setTimeout(function() {

console.log(this.name);

}, 3000);

}

showName.call(student);

`

结果3秒后输出的是undefined,因为定时器里的函数是全局调用,this指向了window,window里没有name属性。这时候用刚才的bind就能解决,或者箭头函数(ES6新特性)也可以,箭头函数的this会继承外层作用域的指向,不用手动切换,更简单。

掌握了这几个规则,this指向就不再是难题,能帮你写出更灵活、更易维护的代码。

上一篇 C / C++ 编程语言在系统开发与性能优化领域的核心应用价值科普