关于javascript:前端开发者应该知道的JS规范

4次阅读

共计 9207 个字符,预计需要花费 24 分钟才能阅读完成。

标准: 导入模块的程序

以有组织的形式引入 ES6 模块将节俭你查找任何找不到或不须要模块的工夫

之前

import {PageHeaderWrapper} from "@ant-design/pro-layout";
import {CustomFormHOC} from "@/components/FormWidget";
import {Form, Card, Button, Divider, message, Alert} from "antd";
import {connect} from "dva";
import PropTypes from "prop-types";
import React, {Component} from "react";
import TransportInfo from "./TransportInfo";
import RecordInfo from "./RecordInfo";
import router from "umi/router";
import styles from "./index.less";

之后

// node_modules
import React, {Component} from "react";
import {Form, Card, Button, Divider, message, Alert} from "antd";
import {connect} from "dva";
import router from "umi/router";
import PropTypes from "prop-types";
import {PageHeaderWrapper} from "@ant-design/pro-layout";
// 我的项目公共模块
import {CustomFormHOC} from "@/components/FormWidget";
// 以后业务耦合模块
import TransportInfo from "./TransportInfo";
import RecordInfo from "./RecordInfo";
// 款式文件
import styles from "./index.less";

之前 的引入是无序的,一个文件可能会很乱,然而当你关上大量文件时候,尝试找到一个特定的包真的很难。

应用 之后 的形式对导入的包进行分组,通过空格行宰割每个模块。又因为文件将保持一致,就能够删除正文了。

标准: 尽可能应用解构

另外一个重要的事件就是避免不必要的嵌套和反复(将对象的属性值保留为局部变量)

  • 对象成员嵌套越深,读取速度也就越慢。所以好的教训法令是:如果在函数中须要屡次读取一个对象属性,最佳做法是将该属性值保留在局部变量中,防止屡次查找带来的性能开销 ( 对象变量防止嵌套过深)
  • 函数参数越少越好,如果参数超过两个,要应用 ES6 的解构语法,这样就不必思考参数的程序了
  • 应用参数默认值 代替应用条件语句进行赋值

在大多数状况下,将大大晋升可读性。

之前

const Page=(deliveryCompany,carrierName,driverInfo,driverInfo)=>{
  return(<Descriptions.Item label="供应商">{deliveryCompany || '未知'}</Descriptions.Item>
                <Descriptions.Item label="承运商">{carrierName || '未知'}</Descriptions.Item>
                <Descriptions.Item label="司机">{driverInfo.driver || '未知'}</Descriptions.Item>
                <Descriptions.Item label="联系方式">{driverInfo.contact || '未知'}</Descriptions.Item>
  );
}

之后

const Page=dataDetail=>{
  const {
    deliveryCompany = '未知',
    carrierName = '未知',
    driverInfo = {driver: '未知', contact: '未知'},
  } = props;

  const {driver, contact} = driverInfo;

  return(<Descriptions.Item label="供应商">{deliveryCompany}</Descriptions.Item>
                <Descriptions.Item label="承运商">{carrierName}</Descriptions.Item>
                <Descriptions.Item label="司机">{driver}</Descriptions.Item>
                <Descriptions.Item label="联系方式">{contact}</Descriptions.Item>
  );
}

标准: 变量和办法的命名约定

对于代码,有一点很重要,就是要晓得一个办法将返回什么,或者通过变量名轻松了解变量的含意(变量语义化),比方

  • JS 采纳 Camel Case 小驼峰式命名
  • 防止名称冗余,保障语义明确
  • 每个常量都须要有意义的变量名(不然看代码的人不晓得这个常量示意什么意思)
动词 含意
can 判断是否可执行某个动作
has 判断是否含有某个值
is 判断是否为某个值
get 获取某个值
set 设置某个值

之前

User.cat = true;
User.admin = true;

function NewUser(age) {
  User.age = 150 - age;
  return User;
}

function add_photo(photo) {User.photo = photo;}

之后

let user = {};

user.hasCat = true;
User.isAdmin = true;

const maxAge = 150;

function getUser(age) {
  User.age = maxAge - age;
  return User;
}

function setUserPhoto(photo) {User.photo = photo;}

之后 展现了如何在命名变量和办法放弃一致性,在以下方面保持一致:

  • 对于布尔类型应用:is, has,should 做前缀
  • 对于办法应用 get/set 做前缀
  • 变量和办法都应用驼峰命名
  • 应用 ES6 的 const 定义常量

之后,组件为注入一些公共变量做筹备,比方 style, className, key 等等,应用开展操作,将一组公共属性传入容器。

标准: 删除弃用代码

很多时候有些代码曾经没有用了,然而没有及时去删除,这样导致代码外面包含很多正文的代码块,好的习惯是提交代码前记得删除曾经确认弃用的代码,例如:一些调试的 console 语句、无用的弃用代码。版本控制系统的存在是有起因的。如果想找旧代码就到 Git history 去找吧。

之前

doStuff();
// doOtherStuff();
// doSomeMoreStuff();
// doSoMuchStuff();

之后

doStuff();

标准: 放弃必要的正文

代码正文不是越多越好,放弃必要的业务逻辑正文,至于函数的用处、代码逻辑等,要通过语义化的命令、简单明了的代码逻辑,来让浏览代码的人疾速看懂。

标准: 应用 Async/Await 代替 Promise 和回调函数

Promise 是较回调而言更好的一种抉择,但 ES7 中的 async 和 await 更胜过 Promise

在能应用 ES7 个性的状况下能够尽量应用他们代替 Promise

之前

require("request-promise")
  .get("https://en.wikipedia.org/wiki/Robert_Cecil_Martin")
  .then(function (response) {return require("fs-promise").writeFile("article.html", response);
  })
  .then(function () {console.log("File written");
  })
  .catch(function (err) {console.error(err);
  });

之后

async function getCleanCodeArticle() {
  try {const request = await require("request-promise");
    const response = await request.get("https://en.wikipedia.org/wiki/Robert_Cecil_Martin");
    const fileHandle = await require("fs-promise");

    await fileHandle.writeFile("article.html", response);
    console.log("File written");
  } catch (err) {console.log(err);
  }
}

标准: 如何捕捉谬误

谬误抛出是个好货色!这使得你可能胜利定位运行状态中的程序产生谬误的地位。

应用 try catch

对捕捉的谬误不做任何解决是没有意义的。

代码中 try/catch 的意味着你认为这里可能呈现一些谬误,你应该对这些可能的谬误存在相应的解决计划(前端监控计划之一)。

之前

try {functionThatMightThrow();
} catch (error) {console.log(error);
}

之后

try {functionThatMightThrow();
} catch (error) {// One option (more noisy than console.log):
  console.error(error);
  // Another option:
  notifyUserOfError(error);
  // Another option:
  reportErrorToService(error);
  // OR do all three!
}

应用 Promise 的 catch

之前

getdata()
  .then((data) => {functionThatMightThrow(data);
  })
  .catch((error) => {console.log(error);
  });

之后

getdata()
  .then((data) => {functionThatMightThrow(data);
  })
  .catch((error) => {// One option (more noisy than console.log):
    console.error(error);
    // Another option:
    notifyUserOfError(error);
    // Another option:
    reportErrorToService(error);
    // OR do all three!
  });

标准: React 相干

一些十分根底的标准这里就不说了,说一些比根底高级一点的 😆

  • 举荐应用函数式 +Hooks 编写代码

恪守 Hooks 规定

不要在循环、条件和嵌套函数内调用 Hooks。当你想有条件地应用某些 Hooks 时,请在这些 Hooks 中写入条件。

错误代码

if (name !== "") {useEffect(function persistForm() {localStorage.setItem("formData", name);
  });
}

应该这样做

useEffect(function persistForm() {if (name !== "") {localStorage.setItem("formData", name);
  }
});

这条规定能确保每次渲染组件时都以雷同的顺序调用 Hooks。这样一来,React 就能在多个 useState 和 useEffect 调用之间正确保留 Hooks 的状态。

应用 ESLint 的 React Hooks 插件

React 团队还创立了一个名为 eslint-plugin-react-hooks 的 ESLint 插件,以帮忙开发人员在本人的我的项目中以正确的形式编写 React Hooks。这个插件可能帮忙你在尝试运行应用程序之前捕捉并修复 Hooks 谬误。

它有两条简略的规定:

  • react-hooks/rules-of-hooks
  • react-hooks/exhaustive-deps

第一条规定只是强制你的代码合乎我在第一个技巧中阐明的 Hooks 规定。第二个规定,exhaustive-deps 用于施行 useEffect 的规定:effect 函数中援用的每个值也应呈现在依赖项数组中。
例如,上面这个 userInfo 组件会触发 exhaustive-deps 正告,因为 userId 变量在 useEffect 外部被援用,但未在依赖项数组中传递:

function UserInfo({userId}) {const [user, setUser] = useState(null);
  useEffect(() => {getUser(userId).then((user) => setUser(user));
  }, []); // no userId here
  return <div>User detail:</div>;
}

以正确的程序创立函数组件

倡议先应用 useState Hook 申明状态变量,而后应用 useEffect Hook 编写订阅,接着编写与组件作业相干的其余函数。

最初,你得返回要由浏览器渲染的元素:

function App() {const [user, setUser] = useState(null);
  const [name, setName] = useState("");
  useEffect(() => {console.log("component is mounted");
  }, []);
  return <h1>React component order</h1>;
}

useState 的用法能够和类组件的状态完全一致,不只用于单个值

许多 useState 示例会向你展现如何通过申明多个变量来申明多个状态:

const [name, setName] = useState("John Doe");
const [email, setEmail] = useState("johndoe@email.com");
const [age, setAge] = useState(28);

然而 useState 实际上既能够解决数组也能够解决对象。你仍旧能够将相干数据分组为一个状态变量,如以下示例所示:

const [user, setUser] = useState({
  name: "John Doe",
  email: "john@email.com",
  age: 28,
});

这里有一个正告。应用 useState 的更新函数更新状态时,以前的状态会替换为新状态。这与类组件的 this.setState 不同,后者的新类中,新状态会与旧状态合并:

const [user, setUser] = useState({
  name: "John",
  email: "john@email.com",
  age: 28,
});
setUser({name: "Nathan"});
// result {name: 'Nathan'}

为了保留以前的状态,你须要创立将以后状态值传递到本身中的回调函数来手动合并它。因为下面的示例已将 user 变量调配为状态值,因而能够将其传递给 setUser 函数,如下所示:

setUser((user) = > ({...user, name: 'Nathan'}));
// result is {name:'Nathan', email: 'john@email.com', age: 28}

依据数据在应用程序生命周期中的变动状况,倡议在各个值彼此独立时将状态拆分为多个变量。
然而对于某些状况,例如构建一个简略的表单,最好将状态分组在一起,以便更轻松地解决更改和提交数据。

简而言之,你须要在多个 useState 调用和单个 useState 调用之间保持平衡。

应用自定义 Hooks 共享利用程序逻辑

在构建应用程序时,你会留神到一些利用程序逻辑会在许多组件中一次又一次地应用。
随着 React Hooks 的公布,你能够将组件的逻辑提取到可重用的函数中作为自定义 Hooks, 比方 ” 非驰名 ” 阿里开源库 ahooks

应用 useContext 防止 prop drilling

prop-drilling 是 React 应用程序中的常见问题,指的是将数据从一个父组件向下传递,通过各层组,直到达到指定的子组件,而其余嵌套组件实际上并不需要它们。

React Context 是一项性能,它提供了一种通过组件树向下传递数据的办法,这种办法无需在组件之间手动传 props。父组件中定义的 React Context 的值可由其子级通过 useContext Hook 拜访。

1. 组件申明

组件名称和定义该组件的文件名称倡议要保持一致

之前

import FooterComponent from "./FooterComponent/index";

之后

import Footer from "./Footer/index";

2. React 中的命名

  • 组件名称:举荐应用大驼峰命名;
  • 属性名称:React DOM 应用小驼峰命令来定义属性的名称,而不应用 HTML 属性名称的命名约定;
  • style 款式属性:采纳小驼峰命名属性的 JavaScript 对象;
// 组件名称
MyComponent;
// 属性名称
onClick;
// 款式属性
backgroundColor;

3.  对齐

// 举荐
<Foo
  superLongParam="bar"
  anotherSuperLongParam="baz"
/>

// 如果组件的属性能够放在一行(一个属性时)就放弃在以后一行中
<Foo bar="bar" />

// 多行属性采纳缩进
<Foo
  superLongParam="bar"
  anotherSuperLongParam="baz"
>
  <Quux />
</Foo>

// 不举荐
<Foo superLongParam="bar"
     anotherSuperLongParam="baz" />

4. 引号

JSX 的属性都采纳双引号,其余的 JS 都应用单引号,因为 JSX 属性 不能蕴含本义的引号, 所以当输出 “don’t” 这类的缩写的时候用双引号会更不便

之前

<Foo bar='bar' />

<Foo style={{left: "20px"}} />

之后

<Foo bar="bar" />

<Foo style={{left: '20px'}} />

4.  为你的组件接管公共变量做好筹备

之前

const UserInfo = (props) => {const { name, sex, age} = props;
  return (
    <div>
      <div> 姓名:{name}</div>
      <div> 性别:{sex}</div>
      <div> 年龄:{age}</div>
    </div>
  );
};

之后

const UserInfo = (props) => {const { name, sex, age, ...rest} = props;
  return (<div {...rest}>
      <div> 姓名:{name}</div>
      <div> 性别:{sex}</div>
      <div> 年龄:{age}</div>
    </div>
  );
};

7.  组件遵循繁多职责准则

组件遵循繁多职责准则(Single Responsibility Principle)能够让你轻松创立和奉献代码,并放弃代码库的整洁。

即容器组件与傻瓜组件。

  • 容器组件负责数据的申请与获取,props/state 的更新。
  • 傻瓜组件只负责接管 props,抛出事件

之前

import React, {useState, useEffect} from "react";
import fetch from "isomorphic-fetch";

const UserInfo = (props) => {const [user, setUser] = useState(null);

  useEffect(() => {async function getUser() {const user = await fetch("/userAppi");

      if (user) {setUser(user);
      }
    }
    getUser();}, []);

  const {name, age} = user;
  return (
    <div>
      <div>{name}</div>
      <div>{age}</div>
    </div>
  );
};

之后

import React, {useState, useEffect} from "react";
import {fetchUser} from "./api";

const UserInfo = (props) => {const { user} = props;

  const {name, age} = user;
  return (
    <div>
      <div>{name}</div>
      <div>{age}</div>
    </div>
  );
};

const UserInfoPage = (props) => {const [user, setUser] = useState(null);

  useEffect(() => {async function getUser() {const user = await fetchUser("/userAppi");

      if (user) {setUser(user);
      }
    }
    getUser();}, []);

  return <UserInfo user={user} />;
};

附加:如果你正在应用类型查看器,请让它发挥作用。
如果你的团队抉择应用类型查看器,那么应用严格模式很重要,以确保它能发挥作用,来达到应用它的目标。

interface UserInfoInterface {
  name: string;
  age: number;
}

const UserInfo = (props: UserInfoInterface) => {const { user} = props;

  const {name, age} = user;
  return (
    <div>
      <div>{name}</div>
      <div>{age}</div>
    </div>
  );
};

参考文档

  1. [[译]晋升你 react 和 js 编码的 5 个技巧](https://mp.weixin.qq.com/s/98…
  2. 团队 React 代码标准制订
  3. 前端团队代码评审 CheckList 清单
  4. 京东凹凸实验室代码标准

最初

在日常工作中你还应用哪些 JavaScript 标准 呢?欢送在评论区留下的你的见解!

感觉有播种的敌人欢送 点赞 关注 一波!

往期文章

react 构建系列

  1. 企业级前端开发标准如何搭建 🛠
  2. 「React Build」之集成 Webpack5/React17
  3. 「React Build」之集成 CSS/Less/Sass/Antd
  4. 「React Build」之集成图片 / 字体
  5. 「React Build」之集成 Redux/Typescript
  6. 「React Build」之应用 Redux-thunk 实现 Redux 异步操作
  7. 「React Build」之集成 React-Router/Antd Menu 实现路由权限
正文完
 0