ESLint no-restricted-properties 规则详解精确禁用指定对象的指定属性【免费下载链接】eslintFind and fix problems in your JavaScript code.项目地址: https://gitcode.com/GitHub_Trending/es/eslint本指南围绕 ESLint 核心规则no-restricted-properties展开讲解如何通过配置精确拦截“特定对象上的特定属性”的读取与调用适用于 API 弃用、模块方法收口、禁止变更性写法等代码治理场景。读完本文你将掌握该规则的全部配置项object、property、message、allowObjects、allowProperties、其底层源码实现机制以及对应的测试用例与实战组合方案。规则是什么no-restricted-properties是一条建议型suggestion规则它允许代码库明确禁止访问“指定对象名上的指定属性键”无论是读取属性的值还是以函数形式调用它都会触发报告。这一能力最常见的两个用途是废弃deprecate某个 API例如禁止使用 Mocha 测试框架中的describe.only强制开发者在提交前去掉.only避免 CI 只跑单条用例限制模块方法的使用例如禁止使用_.extend引导团队改用原生Object.assign。规则本身不做任何代码修复无fixer它只负责“发现并报告”。从规则的元信息可以确认其默认配置recommended: false即它不在eslint:recommended推荐集中需要团队按需显式开启见 lib/rules/no-restricted-properties.js。该规则同时适用于点号访问obj.prop与解构访问const { prop } obj并且支持可选的自定义消息message用于提示替代 API 或说明限制原因。配置项详解规则接受一个对象数组每个对象至少指定对象名和/或属性名。以下逐一给出可直接复制的配置片段。基础形式指定对象 属性{ rules: { no-restricted-properties: [2, { object: disallowedObjectName, property: disallowedPropertyName }] } }可以同时声明多个“对象/属性”组合并为每个组合附加可选的message{ rules: { no-restricted-properties: [2, { object: disallowedObjectName, property: disallowedPropertyName }, { object: disallowedObjectName, property: anotherDisallowedPropertyName, message: Please use allowedObjectName.allowedPropertyName. }] } }省略对象名全局禁用某个属性若省略object则任何对象上的该属性都会被禁用。典型场景是禁止__defineGetter__{ rules: { no-restricted-properties: [2, { property: __defineGetter__, message: Please use Object.defineProperty instead. }] } }省略属性名禁用某个对象的所有属性若省略property则该对象的任意属性访问都会被禁用。例如禁止require.resolve这类用法、只允许直接调用require(){ rules: { no-restricted-properties: [2, { object: require, message: Please call require() directly. }] } }allowObjects全局禁用一个属性但放行特定对象当某个属性需要全局禁止、但又允许特定对象使用时使用allowObjects。例如禁止可变地调用push但放行路由对象上的router.push{ rules: { no-restricted-properties: [2, { property: push, allowObjects: [router], message: Prefer [...array, newValue] because it does not mutate the array in place. }] } }allowProperties禁用对象的所有属性但放行特定属性与上一条对称当需要禁用某对象的全部属性、仅保留白名单属性时使用allowProperties{ rules: { no-restricted-properties: [2, { object: config, allowProperties: [settings, version], message: Accessing other properties is restricted. }] } }互斥约束需要注意两组互斥关系二者不可同时出现在同一个配置对象中allowObjects不能与object同时使用一个限制的是“属性名”一个限制的是“对象名”语义冲突allowProperties不能与property同时使用理由相同。从规则 schema 可以看出这一约束是在配置校验阶段强制执行的见 lib/rules/no-restricted-properties.jsanyOf: [ { required: [object] }, { required: [property] }, ], not: { anyOf: [ { required: [allowObjects, object] }, { required: [allowProperties, property] }, ], },即每个配置对象必须提供object或property中的至少一个同时禁止“allowObjectsobject”与“allowPropertiesproperty”的组合additionalProperties: false表示不接受任何未列出的字段uniqueItems: true则保证整个配置数组内没有重复项。错误示例incorrect以下代码均会被规则报告。第一个例子同时演示了“读取属性值”和“作为函数调用”两种被拦截的形态/* eslint no-restricted-properties: [2, { object: disallowedObjectName, property: disallowedPropertyName }] */ const example disallowedObjectName.disallowedPropertyName; /*error Disallowed object property: disallowedObjectName.disallowedPropertyName.*/ disallowedObjectName.disallowedPropertyName(); /*error Disallowed object property: disallowedObjectName.disallowedPropertyName.*/全局禁用属性__defineGetter__时点号访问、解构、函数参数解构都会被拦截/* eslint no-restricted-properties: [2, { property: __defineGetter__ }] */ foo.__defineGetter__(bar, baz); const { __defineGetter__ } qux(); ({ __defineGetter__ }) {};禁用require对象的所有属性时require.resolve属于违规/* eslint no-restricted-properties: [2, { object: require }] */ require.resolve(foo);配合allowObjects时白名单之外的对象的push调用会被拦截/* eslint no-restricted-properties: [2, { property: push, allowObjects: [router], }] */ myArray.push(5);配合allowProperties时白名单之外的属性访问会被拦截/* eslint no-restricted-properties: [2, { object: config, allowProperties: [settings, version] }] */ config.apiKey 12345; config.timeout 5000;正确示例correct与错误示例一一对应以下代码全部通过校验/* eslint no-restricted-properties: [2, { object: disallowedObjectName, property: disallowedPropertyName }] */ const example disallowedObjectName.somePropertyName; allowedObjectName.disallowedPropertyName();/* eslint no-restricted-properties: [2, { object: require }] */ require(foo);/* eslint no-restricted-properties: [2, { property: push, allowObjects: [router, history], }] */ router.push(/home); history.push(/about);/* eslint no-restricted-properties: [2, { object: config, allowProperties: [settings, version] }] */ config.settings { theme: dark }; config.version 1.0.0;源码实现原理理解规则的内部实现有助于写出更精准的配置。规则的核心逻辑位于 lib/rules/no-restricted-properties.js大致分为三步。第一步配置分类——三个 Mapcreate函数首先读取context.options然后依据“是否省略 object / property”将配置归入三个容器见 lib/rules/no-restricted-properties.jsrestrictedProperties同时指定了object与property的精确组合用嵌套Map对象名 → 属性名 → 配置保存globallyRestrictedObjects只指定了object省略property连同其allowProperties与message保存globallyRestrictedProperties只指定了property省略object连同其allowObjects与message保存。这种分类正是“省略某个字段即全局生效”这一语义的实现基础。第二步监听两种 AST 节点规则返回的 visitor 只关心两类节点见 lib/rules/no-restricted-properties.jsMemberExpression处理obj.prop/obj[prop]形式的成员访问同时覆盖obj.prop()调用调用本身也是CallExpression其被调用对象仍是MemberExpressionObjectPattern处理解构例如const { bar } foo、let bar; ({ bar } foo)、函数默认参数解构function qux({ bar } foo) {}。代码会从父节点VariableDeclarator、AssignmentExpression、AssignmentPattern回溯出被解构的源对象标识符名称再对其中的每个解构属性逐一检查。第三步静态属性名解析与命中判定checkPropertyAccess是核心判定函数见 lib/rules/no-restricted-properties.js先用astUtils.getStaticPropertyName(node)解析出属性名——只对静态属性名生效。该工具函数见 lib/rules/utils/ast-utils.js支持Identifier属性非计算访问、字符串字面量计算访问obj[foo]、ChainExpression可选链以及解构中的Property节点等对动态计算属性如obj[key]返回null规则随之跳过不做误报分别在精确组合表、全局对象表、全局属性表中查找命中项命中后若配置了allowObjects/allowProperties会用isAllowed检查当前访问是否位于白名单内见 lib/rules/no-restricted-properties.js白名单命中则不报告最终报告使用两种消息模板见 lib/rules/no-restricted-properties.js{{objectName}}.{{propertyName}} is restricted from being used.{{allowedPropertiesMessage}}{{message}} {{propertyName}} is restricted from being used.{{allowedObjectsMessage}}{{message}}其中allowedObjectsMessage/allowedPropertiesMessage会动态拼出“仅允许在以下对象上使用”“仅允许以下属性”的说明文字message则为自定义提示未配置时保持为空。行为边界从实现可推断规则只检查静态属性名动态计算属性如obj[dynamicKey]不会被报告规则按名称匹配而非类型/作用域分析只要标识符文本一致即命中例如require.resolve与require[resolve]都会被{ object: require }拦截对应测试见 tests/lib/rules/no-restricted-properties.js对obj.prop的检查只针对最外层成员访问例如foo.bar.baz中foo.bar与bar.baz是两个独立的MemberExpression节点配置{ property: bar }会命中foo.bar对应测试见 tests/lib/rules/no-restricted-properties.js。测试覆盖验证该规则拥有非常完整的测试套件共 1100 行用例见 tests/lib/rules/no-restricted-properties.js覆盖了配置解析的绝大部分边界精确组合对象/属性匹配、非匹配对象放行、非匹配属性放行、调用与读取双形态第 22-104 行省略 object 的全局属性限制foo.bar不匹配{ property: baz }、foo()不匹配{ object: foo }等第 105-150 行解构场景let {baz: bar} foo、嵌套解构let {baz: {bar: qux}} foo、数组解构、函数参数解构、赋值解构、带默认值的解构等第 151-230 行与第 605-799 行并验证了“解构重命名”场景——{baz: bar}中实际解构的属性名是baz而非bar计算属性foo[__proto__]、正则字面量作为计算键、obj[#foo]私有名等第 438-458 行、第 550-564 行、第 796-810 行allowObjects / allowProperties 白名单白名单内放行、白名单外报告以及报告消息中白名单说明文案的拼接第 236-300 行、第 1010-1139 行链式访问foo.bar.baz只报告命中的那一层第 460-548 行。这些测试不仅验证了正确/错误判定还精确断言了消息data字段objectName、propertyName、message、allowedObjectsMessage、allowedPropertiesMessage的拼接结果可作为理解规则报告格式的参考。与相关规则的配合规则的元信息声明了两条相关规则见 docs/src/rules/no-restricted-properties.mdno-restricted-globals禁用指定的全局变量如isNaN、undefined适用于限制全局命名空间的使用no-restricted-syntax通过 AST 选择器禁用任意语法结构粒度更底层、更灵活可表达“任何MemberExpression 特定对象名”等复杂模式。三者形成互补no-restricted-properties专门处理“对象上的属性”no-restricted-globals处理全局标识符no-restricted-syntax则提供通用兜底。选型时优先使用语义最聚焦的规则配置更直观、报告更可读。何时不应使用此规则官方文档明确建议见 docs/src/rules/no-restricted-properties.md如果代码库中没有任何需要限制的“对象/属性”组合就不应启用此规则。它是一条纯“添加限制”的规则没有默认推荐值若配置为空列表则规则直接返回空 visitor见 lib/rules/no-restricted-properties.js不产生任何检查效果。实战小结在项目中使用no-restricted-properties的推荐流程明确限制目标梳理需要废弃的 API 或需要收口的模块方法逐条列出“对象名 属性名”选择配置形态单一对象单一属性用精确组合整个对象禁用用allowProperties白名单某个属性全局禁用用allowObjects白名单编写替代提示为每个限制项配置message告知替代 API如Object.assign或替代写法如不可变push让开发者无需翻文档即可迁移灰度推行先在 CI 中开启该规则配合存量代码清理通过后保留为长期约束防止 API 再次被引入。通过这份“配置 源码 测试”的全景解析你可以把no-restricted-properties从一条简单规则升级为团队 API 治理与代码风格收口的得力工具。【免费下载链接】eslintFind and fix problems in your JavaScript code.项目地址: https://gitcode.com/GitHub_Trending/es/eslint创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考