【个人总结】 从eslint和stylelint中我们可以学到什么代码技巧

在一般的项目配置中,通常会使用eslint和stylelint来规范代码质量。除了解决格式问题,还有一些需要注意的代码写法误区和需要注意的地方。翻了几天的stylelint,eslint的官网,再加上我之前的项目的一些东西,总结出了这篇文章。欢迎讨论

eslint (JavaScript)

一目了然的配置:

ruby 复制代码
{
    "constructor-super": "error", // 强制要求构造函数中的super()调用
    "no-cond-assign" : "error", // 不允许在条件语句中使用赋值运算符
    "no-func-assign":"error", // 禁止重新分配函数
    "no-this-before-super":"error", // 禁止在super构造函数中使用this之前使用
    "no-unreachable":"error", // 禁止在return、throw、continue、break语句之后出现不可达代码
    "eqeqeq":"error" // 强制使用全等(===)比较
}

10.5.1 require-atomic-updates | 重要

错误示例如下:

javascript 复制代码
let Result = 0;
let getResult = (time)=>{
    return new Promise((resolve)=>{
        setTimeout((time)=>{
            resolve(time)
        },time,time)
    })
}
async function addResult(pageNum) {
    Result += await getResult(pageNum); // 错误的输出 输出 1000
}

Promise.all([addResult(500),addResult(1000)]).then(() => {
  console.log('Count:', Result);
});

我们可以看到一个现象,我想在 Promise.all 中将 500 和 1000加起来。但是返回结果输出了1000。原因是新值在未被读取的情况下被覆盖,下面一开始的result就是直接被覆盖了。解决的方法是将await放在前面,将函数调用放在前面。另外需要小心使用+=,包括yield也绝不能放在后面。

javascript 复制代码
let Result = 0;
let getResult = (time)=>{
    return new Promise((resolve)=>{
        setTimeout((time)=>{
            resolve(time)
        },time,time)
    })
}
async function addResult(pageNum) {
    // 正确的输出 输出 1500
    Result = await getResult(pageNum) + Result;
}

Promise.all([addResult(500),addResult(1000)]).then(() => {
  console.log('Count:', Result);
});

10.5.2 no-await-in-loop

简单来说,尽量不要在循环中使用await,除非你的循环迭代实际上是相互独立的,或者一次迭代的输出可以用作另一次迭代的输入,或者循环用于重试不成功的异步操作,或者用于防止代码并行发送过多的请求。在这些情况下,使用await在循环中是有意义的。

10.5.3 no-compare-neg-zero

这个规则的主要原因是JavaScript中的一个特性,即 +0 === -0 相等。因此,当遇到这种情况时,最好使用 Object.is() 来进行比较。

10.5.4 no-constructor-return

不允许在JavaScript的类构造函数中返回值,否则在使用new时将得到一个空对象。

10.5.5 no-unsafe-finally

finally块中,如果有return或者throw语句,它们会先执行。这是由于JavaScript的特性,所以需要注意在finally中使用return的特性。

javascript 复制代码
(() => {
    try {
        console.log(33)
        return 1; // 输出33
    } catch(err) {
        return 2;
    } finally {
        throw 3; // 输出3
    }
})();

10.5.6 no-fallthrough

arduino 复制代码
case a:
    do
case b
    do
case c
    do

有些人可能会以为用 case 来写的话,a成立就不会继续执行了,但是事实是 case 是如果 不加上 break 是能够一直执行下去的。这会造成无谓的性能损耗和不可预料的后果。因此最好加上break

10.5.7 no-new-symbol

要使用Symbol来创建Symbol,而不是使用new Symbol

10.5.8 no-empty-pattern

当使用解构时,有可能创建一个没有效果的模式。当嵌入对象解构模式右侧使用空花括号时,会发生这种情况。下面是示例:

ini 复制代码
const foo = {c: 232323}
var {b= {}} = foo;
console.log(b)

10.5.9 no-setter-return

就是说 像是 对象里面的 set 方法不要 返回值,因为 返回值没有用。一般就是 this.xxx = xxx

普通 变量 foo.a 的 时候 会触发 set 方法

ts 复制代码
let  foo = {
    set a(value) {
        this.val = value;
        return value;
    }
};

class 里面 也一样 静态属性是

ts 复制代码
class a{
    static set a(value) {
        this.val = value;
    }
};

但是特别需要注意一点。proxy 是必须要 return 值回来的。正确写法是类似这样

ts 复制代码
let b = new Proxy(store, {
    get(...args) {
        return Reflect.get(...args)
    },
    set(...args) {
        Reflect.set(...args)
    },
})

10.5.10 no-prototype-builtins | guard-for-in

no-prototype-builtins规则不允许直接在对象实例上调用某些方法。主要针对的对象是指node作为服务器的对象。我们知道一个对象中有着hasOwnProperty这个属性,但是如果我们返回的数据里面有这样一个对象:

bash 复制代码
let arr = {
    "hasOwnProperty": "为了防止这些客户端搞事情导致服务器崩溃",
    "id": 5
}

但是如果我们要是不知道这个东西而调用arr.hasOwnProperty("id")这个方法,肯定会报错hasOwnProperty is not a function。因此在guard-for-in规则下需要这样写:

ini 复制代码
var hasBarProperty = Object.prototype.hasOwnProperty.call(foo, "bar");

10.5.11 dot-notation | 点符号 -属性 | 变量-方括号

可以使用点符号 (foo.bar) 或方括号符号 (foo["bar"]) 访问属性。然而,点表示法通常是首选,因为它更容易阅读、更简洁。但是如果属性名是一个变量,就必须使用方括号符号。

10.5.12 prefer-promise-reject-errors

对于Promises中用户定义的错误,仅将内置Error对象的实例传递给函数被认为是良好的做法。对象自动存储堆栈跟踪,可用于通过确定错误的来源来调试错误。如果Promise因无值而被拒绝,则可能很难确定拒绝发生在哪里。

javascript 复制代码
Promise.reject(new Error("something bad happened"));

10.5.13 prefer-rest-params

这个规则的原因是,ES2015引入了剩余参数(rest parameters)来更方便地处理可变参数的函数。相比之下,使用arguments存在一些不足之处。

以下是使用剩余参数替代arguments的优点:

  1. 明确性:剩余参数允许你在函数声明中显式地定义参数,提高了代码的可读性和可维护性。相比之下,arguments是一个隐式对象,并且没有明确的方式来知道参数的数量或含义。
  2. 数组功能:剩余参数将可变参数作为数组提供,使你能够直接使用数组相关的方法,如forEachmapreduce等。这让代码更加简洁和语义清晰。
  3. 参数数量与限制:使用剩余参数,你可以更容易地对参数数量进行限制和验证,例如使用解构赋值来确保函数参数的结构。而arguments对象没有提供内置的方法来访问或验证参数。
  4. 函数箭头和匿名函数:在箭头函数和匿名函数中,不能使用arguments对象,但可以使用剩余参数。
javascript 复制代码
function sum(...numbers) {
  return numbers.reduce((total, num) => total + num, 0);
}

console.log(sum(1, 2, 3, 4)); // 输出: 10

stylelint (CSS)

以下是stylelint中一些规则的描述:

json 复制代码
{
    "property-no-unknown": true, // 不允许未知的属性
    "selector-anb-no-unmatchable": true, // 伪类给你一个0或者0n,但是css选择器是0往上面走的
    "declaration-block-no-shorthand-property-overrides": true, // 速记属性覆盖padding-left: 10px; padding: 20px;一下子就被覆盖了
    "no-invalid-position-at-import-rule": true // @import放在最顶上
}

10.6.1 function-calc-no-unspaced-operator

此规则检查calc中运算符之前是否有单个空格或换行符加缩进-,以及该运算符之后是否有单个空格或换行符。

css 复制代码
a { 
    top: calc(1px+ 2px); 
}

这样是错的,注意一下运算符号:

css 复制代码
top: calc(1px + 2px); 

这样就对了,否则calc不会执行。

10.6.2 keyframe-declaration-no-important

css 复制代码
@keyframes foo {
  from {
    opacity: 0;
  }
  to {
    opacity: 1 !important;
  }
}

在keyframe中不应该使用!important,因为它可能会导致未知的问题。

10.6.3 media-query-no-invalid

下面的是错误的:

scss 复制代码
@media (width == 100px) {
    
}

@media not(min-width: 300px) {

}

这是正确的:

scss 复制代码
@media (width = 100px) {
    
}
@media (width: 100px) {
    
}
@media not (min-width: 300px) {
    
}

规则如下:

  • 只有=>=<=,没有==
  • not前后需要空格

10.6.4 declaration-block-no-redundant-longhand-properties

在样式中一些属性有简写属性,尽量使用简写属性。例如,flex-flow属性值可以是 row wrap,它合并了flex-directionflex-wrap的写法。以下是一些示例:

css 复制代码
/* 定位和边距示例 */
.position-example {
  position: absolute;
  inset: 20px;
  background-color: #f0f0f0;
  padding: 10px;
  border: 1px solid #333;
}

/* 背景示例 */
.background-example {
  background: #f0f0f0 url("example-background.png") no-repeat center;
  height: 200px;
  width: 300px;
  padding: 20px;
}

/* 字体示例 */
.font-example {
  font: italic bold 16px Arial, sans-serif;
  padding: 10px;
}

/* 边框示例 */
.border-example {
  border: 2px dashed #999;
  border-top: 1px solid #333;
  border-radius: 10px;
  padding: 20px;
}

/* 过渡效果示例 */
.transition-example {
  width: 200px;
  height: 100px;
  background-color: #f0f0f0;
  transition: width 0.5s ease-in-out;
}
.transition-example:hover {
  width: 300px;
}

/* 动画示例 */
@keyframes example-animation {
  0% {
    transform: scale(1);
    background-color: #f0f0f0;
  }
  100% {
    transform: scale(1.2);
    background-color: #ffcc00;
  }
}
.animation-example {
  width: 100px;
  height: 100px;
  background-color: #f0f0f0;
  animation: example-animation 2s infinite alternate;
}

/* 弹性布局示例 */
.flex-example {
  display: flex;
  flex-flow: row wrap; /* flex-direction, flex-wrap */
  justify-content: space-between;
  align-items: center;
}
.flex-item {
  width: 100px;
  height: 100px;
  background-color: #f0f0f0;
  margin: 10px;
}

/* 网格布局示例 */
.grid-example {
  display: grid;
  grid-template: 100px 100px / 1fr 1fr;
  grid-gap: 10px;
  padding: 10px;
}
.grid-item {
  background-color: #f0f0f0;
  padding: 20px;
}

/* 文字修饰示例 */
.text-decoration-example {
  text-decoration: underline overline wavy red;
  padding: 10px;
}

/* 文字着重号示例 */
.text-emphasis-example {
  font-size: 24px;
  text-emphasis: open circle gold;
  padding: 10px;
}

/* 遮罩示例 */
.mask-example {
  width: 200px;
  height: 200px;
  background-image: url("mask-image.png");
  background-size: cover;
  mask: url("mask-image.png") center / contain;
}

10.6.5 no-invalid-position-at-import-rule

任何@import规则都必须位于样式表中所有其他有效的at规则和样式规则之前(忽略@charset@layer),否则该@import规则无效。

相关推荐
腾讯TNTWeb前端团队6 小时前
helux v5 发布了,像pinia一样优雅地管理你的react状态吧
前端·javascript·react.js
范文杰9 小时前
AI 时代如何更高效开发前端组件?21st.dev 给了一种答案
前端·ai编程
拉不动的猪9 小时前
刷刷题50(常见的js数据通信与渲染问题)
前端·javascript·面试
拉不动的猪10 小时前
JS多线程Webworks中的几种实战场景演示
前端·javascript·面试
FreeCultureBoy10 小时前
macOS 命令行 原生挂载 webdav 方法
前端
uhakadotcom11 小时前
Astro 框架:快速构建内容驱动型网站的利器
前端·javascript·面试
uhakadotcom11 小时前
了解Nest.js和Next.js:如何选择合适的框架
前端·javascript·面试
uhakadotcom11 小时前
React与Next.js:基础知识及应用场景
前端·面试·github
uhakadotcom11 小时前
Remix 框架:性能与易用性的完美结合
前端·javascript·面试
uhakadotcom11 小时前
Node.js 包管理器:npm vs pnpm
前端·javascript·面试