十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

eslint-plugin-unicorn no-this-outside-of-class 规则解析:让 `this` 只出现在类与显式绑定中

eslint-plugin-unicorn no-this-outside-of-class 规则解析:让 `this` 只出现在类与显式绑定中 eslint-plugin-unicorn no-this-outside-of-class 规则解析让this只出现在类与显式绑定中【免费下载链接】eslint-plugin-unicornMore than 300 powerful ESLint rules项目地址: https://gitcode.com/GitHub_Trending/es/eslint-plugin-unicorn导读no-this-outside-of-class是 eslint-plugin-unicorn 内置的一条严格规则用于禁止在类class之外的一切位置使用this。它从规则层面强制 JavaScript 开发者以 class 语法或 TypeScript 显式this参数来承载有状态代码从而规避构造函数、手动修补原型、对象字面量方法、顶层this以及依赖隐式绑定的回调 API 带来的混乱。读完本文你将掌握该规则的完整判定逻辑、所有违规与合法场景、TypeScript 支持范围以及它在recommended/unopinionated两套预设配置中的启用情况。规则定位与配置状态规则文档docs/rules/no-this-outside-of-class.md规则实现rules/no-this-outside-of-class.js规则导出rules/index.js测试用例test/no-this-outside-of-class.js从实现文件的meta定义看该规则具有以下特征rules/no-this-outside-of-class.js#L68-L85type: problem定位为“问题类”规则即它标记的是很可能导致错误或反模式的代码recommended: true已在recommended预设配置中默认启用schema: []不接收任何配置选项规则本身不可调参languages: [js/js]仅作用于 JavaScript 语法TypeScript 场景通过同一解析链路中识别显式this参数来实现错误消息Do not use this outside of classes.配置启用情况来自规则文档自身说明该规则在 ✅recommended配置中启用在 ☑️unopinionated配置中禁用。这意味着如果你使用unicorn/recommended预设规则开箱即生效如果你更倾向不干预个人风格的unopinionated预设则该规则不会打扰你。项目两套预设的说明可参见 readme.md。核心设计思想状态必须有明确的接收者规则文档开门见山地定义了它的立场this只应在以下两种场景中使用——JavaScript class 语法定义了接收者或 TypeScript 显式声明了this参数。对于有状态对象规则鼓励优先使用 class而不是依赖构造函数、手工修补的 prototype、对象字面量方法、顶层this或依赖隐式绑定this的回调 API。这是一条刻意严格intentionally strict的规则。文档明确列出了几种不支持的模式Vue options 风格的方法methods: { refresh() { this.list ... } }——尽管这种写法在 Vue 生态中极为常见普通对象方法中依赖隐式this绑定的写法SDK 回调中依赖隐式this绑定的写法。如果这些模式是有意为之文档建议对该文件或代码块禁用此规则。判定原理从ThisExpression向上遍历作用域边界要理解规则为什么把某些代码判为违规、把另一些判为合法需要看核心函数isAllowedThisBindingrules/no-this-outside-of-class.js#L27-L50。规则在遍历 AST 时监听ThisExpression节点rules/no-this-outside-of-class.js#L55-L66并对每个this从当前位置沿parent链一路向上回溯按以下优先级裁决箭头函数ArrowFunctionExpression不构成作用域边界直接continue继续向上找。因为箭头函数不绑定自己的this它内部的this与外部上下文一致非箭头函数FunctionDeclaration / FunctionExpression这是关键分界点。只有当该函数满足以下任一条件时this才合法它是类的方法isClassMethodFunction即parent是MethodDefinition且该函数就是方法的值rules/no-this-outside-of-class.js#L13-L15它显式声明了this参数hasThisParameter即参数列表中存在名为this的 Identifierrules/no-this-outside-of-class.js#L10-L11。否则this立刻被判为违规静态块StaticBlock类静态初始化块内的this合法直接返回true类字段AccessorProperty / PropertyDefinition如果this是类字段的初始值isClassFieldValuerules/no-this-outside-of-class.js#L17-L22同样合法返回true遍历到根部仍无合法边界返回false触发报错。正是这套“向上冒泡、遇非箭头函数即裁决”的算法决定了该规则一系列看似微妙的行为——例如类方法里的普通函数闭包会被报错而箭头函数则安然无恙。违规示例六类典型反模式规则文档给出了三组核心示例第一组针对“接收者来源不明确”的场景// ❌ 构造函数风格this 依赖 new 调用的隐式绑定 function Foo(value) { this.value value; } // ❌ 对象字面量方法this 依赖调用方隐式绑定 const foo { method() { return this.value; } }; // ❌ 手工修补 prototype Foo.prototype.method function () { this.value(); };对应的测试用例覆盖了更多变体test/no-this-outside-of-class.js#L106-L222包括顶层this.value;、const getValue () this.value;顶层箭头函数、普通函数声明function foo() { return this.value; }、函数表达式const foo function () { ... };、IIFE(function () { this.value 1; })();、getter/setter 形式的对象属性、SDK 回调new SDK({ onReady: function () { this.value; } })等。这些用例都无一例外被判为违规。第二组示例展示了“类方法内部的普通函数”这一隐藏陷阱// ❌ 类方法内部嵌套普通函数this 指向丢失 class Foo { method() { function getValue() { return this.value; } return getValue(); } } // ✅ 改用箭头函数捕获外层类的 this class Foo { method() { const getValue () this.value; return getValue(); } }测试用例还补充了一个有意思的边界类字段如果被赋值为普通函数字段内使用this同样违规value function () { return this.value; };而箭头函数字段则合法value () this.defaultValue;——原因正是箭头函数不构成作用域边界this沿链向上最终落在类字段这个合法接收者上。合法场景类内部的this全集合文档给出了最标准的合法写法——class 语法// ✅ class Foo { constructor(value) { this.value value; } method() { return this.value; } }测试文件将合法场景扩充为完整的“类内this使用图谱”test/no-this-outside-of-class.js#L6-L104几乎每一处都能在实现算法的第 3、4 条规则中找到依据实例方法 / 静态方法 / getter / setter / 私有方法constructor()、static method()、get value()、set value(value)、#method()内使用this均合法参数默认值methodWithDefault(value this.value)合法类字段初始值实例字段与静态字段均可如value this.defaultValue;、static value this.defaultValue;静态块static { this.value 1; }合法静态块内的箭头函数同理static { const update () this.value 1; update(); }类方法内的箭头函数method() { const getValue () this.value; return getValue(); }合法类方法内嵌套另一个类内部类的method()、extends this.Base、计算键[this.key]() {}、类字段[this.key] 1均合法——因为嵌套类自身提供了合法的this接收者向上遍历在内层类方法处即返回true。注意最后一点与“类外违规”形成对照测试用例中的无效代码包含class Foo { [this.key]() {} }、class Foo { [this.key] 1; }、class Foo extends this.Base {}test/no-this-outside-of-class.js#L210-L221——当this出现在类自身的计算键或extends子句中而非嵌套类内部时向上遍历会穿过类定义继续向上最终找不到合法接收者因此报错。这精确体现了“只有类内部语法点才是合法接收者类定义外壳本身不是”的设计。TypeScript显式this参数是唯一豁免规则文档的第三个示例给出了 TypeScript 下的合法写法// ✅ TypeScript const foo { method(this: Foo) { return this.value; } };这正是实现中hasThisParameter的作用只要非箭头函数在参数列表里显式声明了this参数即使它身处对象字面量或普通函数中也被视为合法。TypeScript 专项测试进一步验证了以下行为test/no-this-outside-of-class.js#L269-L341合法function validator(this: TrackedModel) { return this.value; }const validator function (this: TrackedModel) { return this.value; };带this参数的对象方法内部的箭头函数validator(this: TrackedModel, value) { const getValue () this.value; return getValue() value; }类accessor字段accessor value this.defaultValue;违规带this参数的对象方法内嵌套普通函数再使用thisgetValue()内部的this无法向上解析到合法边界普通对象方法无this参数内的this箭头函数不能声明this参数const validator (this: TrackedModel) this.value;直接报错——箭头函数的this词法绑定无法被显式参数改写普通函数未声明this参数function validator(value: TrackedModel) { return this.value; }报错类accessor字段使用计算键引用外部thisaccessor [this.key] 1;报错。可见规则在 TypeScript 下的态度是显式声明即信任隐式绑定一律拒绝。与 Vue、CommonJS 等环境的交互由于 Vue options 风格的methods依赖框架运行时把this绑定到组件实例该规则无法识别这种隐式约定因此会对 Vue 组件方法中的this报错。测试专门用test.vue验证了这一点test/no-this-outside-of-class.js#L249-L267script export default { methods: { refresh() { this.list getList(); } } } /script该片段在 Vue 场景测试中被判为 1 个错误。同理普通export default { methods: { refresh() { this.list ... } } }在纯 JS 测试中也被判违规test/no-this-outside-of-class.js#L200-L208。另外测试还针对commonjs与script两种源码类型做了专项快照验证test/no-this-outside-of-class.js#L224-L247确认无论模块体系如何顶层thisthis.value;都会被一致地报告为违规。如何应对禁用策略与迁移建议规则文档明确指出由于规则刻意严格当团队确实依赖 Vue options 方法、对象方法或 SDK 回调的隐式this绑定且这是有意设计时应当针对该文件或代码块禁用规则而不是试图绕开检查。常用做法// 文件级禁用eslint 配置或注释 /* eslint unicorn/no-this-outside-of-class: off */// 块级禁用 /* eslint-disable unicorn/no-this-outside-of-class */ const foo { method() { return this.value; } }; /* eslint-enable unicorn/no-this-outside-of-class */对于希望从根本上消化的代码推荐的迁移路径是文档所强调的把有状态对象改写成 class或在 TypeScript 中为相关函数补充显式this参数用明确的接收者声明替代隐式绑定。小结no-this-outside-of-class以“向上遍历作用域、非箭头函数即裁决”的精简算法把this的合法使用边界牢牢圈定在 class 方法、类字段、静态块与显式 TypeScriptthis参数之内。它不提供任何配置项启用即全量生效适合作为代码库中推行 class-first 风格的强制性约束而在 Vue、SDK 回调等场景中则应结合文件级禁用灵活使用。想深入观察规则的每一个判定分支可直接阅读 rules/no-this-outside-of-class.js 与 test/no-this-outside-of-class.js 中成对的合法/违规用例。【免费下载链接】eslint-plugin-unicornMore than 300 powerful ESLint rules项目地址: https://gitcode.com/GitHub_Trending/es/eslint-plugin-unicorn创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表