JavaScript中this关键字作用域理解困惑及代码疑问
搞懂JavaScript中
this的全局绑定问题 嘿,我完全理解你在啃JavaScript的this关键字时有多懵——这玩意儿绝对是新手入门的“拦路虎”之一!先帮你拆解一下你提到的这段代码,再说说为什么讲师说这是不良实践,以及怎么避免踩坑。
首先先把你的代码格式化一下,方便分析:
var person = "roht" function whatIsThis() { return this console.log(this) // 注意:这里的console不会执行,因为前面已经return了 } function variable (){ this.person = "max" } variable() console.log(person) whatIsThis()
为什么this.person会绑定到全局对象?
在非严格模式下,直接调用一个普通函数(既不是作为对象的方法调用,也没用new、call/apply/bind这类方式),函数内部的this会自动绑定到全局对象:
- 在浏览器环境里,全局对象是
window;在Node.js环境里是global。 - 你一开始用
var person = "roht"声明的变量,本身就是全局对象的一个属性(因为var声明的全局变量会挂载到全局对象上)。所以当你调用variable()时,this.person = "max"本质上是在修改全局对象的person属性,自然会覆盖你一开始的"roht",最后console.log(person)就会输出"max"。
另外提一句:whatIsThis()里的return this会直接返回全局对象,后面的console.log(this)根本不会执行哦。
为什么这是不良实践?
- 污染全局命名空间:全局对象上的属性是所有脚本共享的,如果其他地方也定义了
person变量,就会互相覆盖,排查bug的时候会头大到怀疑人生。 - 代码可读性差:别人看代码时,很难一眼看出
person是在哪里被修改的,维护起来成本极高。 - 不可预测性:如果后续代码不小心开启了严格模式(
'use strict'),普通函数调用时this会变成undefined,这时候this.person = "max"会直接抛出错误,代码直接崩掉。
怎么写才是正确的姿势?
给你几个替代方案,按需选择:
1. 用局部作用域隔离变量
用立即执行函数表达式(IIFE)把代码包裹起来,避免污染全局:
(function() { // 用let/const代替var,避免变量提升和全局挂载问题 let person = "roht"; function changePersonName() { // 直接修改局部变量,根本不需要this person = "max"; } changePersonName(); console.log(person); // 输出 "max" })();
2. 用对象/类封装数据和行为
如果是要处理“人物”这类有属性和行为的逻辑,用对象或者类更合理,这时候this的指向也更清晰:
// 用普通对象 const person = { name: "roht", changeName(newName) { // 这里的this指向person对象本身 this.name = newName; } }; person.changeName("max"); console.log(person.name); // 输出 "max" // 用ES6类(更适合复杂的实例化场景) class Person { constructor(name) { this.name = name; } changeName(newName) { this.name = newName; } } const myPerson = new Person("roht"); myPerson.changeName("max"); console.log(myPerson.name); // 输出 "max"
3. 用闭包或者参数传递
如果只是要在函数里修改变量,也可以用闭包或者把变量作为参数传递:
function createNameChanger(initialName) { let name = initialName; return function(newName) { name = newName; return name; }; } const changeName = createNameChanger("roht"); changeName("max"); console.log(changeName()); // 输出 "max"
最后再帮你梳理下this的核心绑定规则
记住这几个场景,下次遇到this就不会慌了:
- 作为对象方法调用:
obj.func()→this指向obj - 用
new调用构造函数:new Func()→this指向新创建的实例对象 - 用
call/apply/bind显式绑定:func.call(obj)→this指向obj - 普通函数调用(非严格模式):
func()→this指向全局对象;严格模式下是undefined
内容的提问来源于stack exchange,提问作者user9504869
相关产品推荐
相关产品推荐

