【个人总结】 从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规则无效。

相关推荐
上官花雨14 分钟前
什么是axios?怎么使用axios封装Ajax?
前端·ajax·okhttp
米奇妙妙wuu15 分钟前
React中 setState 是同步的还是异步的?调和阶段 setState 干了什么?
前端·javascript·react.js
李刚大人18 分钟前
react-amap海量点优化
前端·react.js·前端框架
闹闹没有闹35 分钟前
socket连接封装
前端
qq_364371722 小时前
Vue 内置组件 keep-alive 中 LRU 缓存淘汰策略和实现
前端·vue.js·缓存
y先森2 小时前
CSS3中的弹性布局之侧轴的对齐方式
前端·css·css3
new出一个对象6 小时前
uniapp接入BMapGL百度地图
javascript·百度·uni-app
你挚爱的强哥7 小时前
✅✅✅【Vue.js】sd.js基于jQuery Ajax最新原生完整版for凯哥API版本
javascript·vue.js·jquery
y先森8 小时前
CSS3中的伸缩盒模型(弹性盒子、弹性布局)之伸缩容器、伸缩项目、主轴方向、主轴换行方式、复合属性flex-flow
前端·css·css3
前端Hardy8 小时前
纯HTML&CSS实现3D旋转地球
前端·javascript·css·3d·html