详解JS ES6编码规范


Posted in Javascript onMay 07, 2021

1、块级作用域

1.1、let取代var

ES6 提出了两个新的声明变量的命令: let 和const。其中,let可以完全取代var,因为两者语义相同,而且let没有副作用。

var命令存在变量提升的特性,而let没有这个命令。

所谓变量提升,即指变量可以先使用,再声明,显然,这种编码规范非常不适合阅读。

1.2、全局常量和线程安全

在let和const之间,优先使用const。

let应出现在单线程模块代码内,而const则非常适合多线程。

// bad
    var a = 1, b = 2, c = 3;

    // good
    const a = 1;
    const b = 2;
    const c = 3;

    // best
    const[a, b, c] = [1, 2, 3];

2、字符串

静态字符串一律使用单引号或者反引号,不推荐使用双引号。

动态字符串(字符串模板)使用反引号。

// bad
const a = "zhaoyi";
const b = a + ", hello.";

// little good
const c = `zhaoyi`;

// very good
const a = 'zhaoyi';
const b = `zhaoyi,${a}, I say your name twice`;

3、解构赋值

1、使用数组成员对变量进行赋值时,优先使用解构赋值。

const arr = ['I', 'love', 'you'];

// bad
const one = arr[0];
const two = arr[1];
const three = arr[2];

// good
const [first, second, third] = arr;

// test
console.log(first, second, third);// I love you

2、函数的参数如果是对象的成员,优先使用解构赋值。

// bad
function getUserInfo(user){
    const name = user.name;
    const age = user.age;
}

// good
function getUserInfo2(user){
    const {name, age} = user;
    console.log(name, age); // 
}

// test
getUserInfo2({name: 'zhaoyi', age: 20}); // zhaoyi 20

3、如果函数返回多个值,优先使用对象的结构赋值,而不是数组的结构赋值。这样便于以后添加返回值,以及更改返回值的顺序。

// bad
function getInfo(input){
    return [left, right];
}

// good
function getInfo2(input){
    return {left, right};
}

// 此处使用对象的解构赋值方式接收返回结果
const {left, right} = getInfo2('test');

4、对象

1、单行定义的对象,最后一个成员不以逗号结尾。多行定义的对象,最后一个成员以逗号结尾。

// bad
const a1 = {k1: v1, k2: v2, k3: v3,};

// good 
const a2 = {k1: v1, k2: v2, k3: v3};

// bad
const b1 = {
    k1: v1,
    k2: v2
};

// good
const b2 = {
    k1: v1,
    k2: v2,
};

2、对象尽量静态化,一旦定义,就不得随意添加新的属性。如果添加属性不可避免,要使用assign方法。

// bad
const a = {};
a.attr = 3;

// if reshape anavoidable(若无可避免)
const b = {};
Object.assign(b, {atrr: 3});

// good
const c = {attr: null};
c.attr = 3;

// test
console.log(a); //{attr: 3}
console.log(b); //{attr: 3}
console.log(c); //{attr: 3}

3、如果对象的属性名是动态的(所谓动态是指,需要通过计算得到),可以在创建对象的时候使用属性表达式定义。(此种情况在开发时,并不多见。)

5、数组

使用扩展运算符(...)复制数组。

// bad
function copyArr1(arr){
    const itemCopy = [];
    for (let index = 0; index < arr.length; index++) {
        itemCopy[index] = arr[index];
    }
    return itemCopy;
}

// good
function copyArr2(arr){
    return [...arr];
}

// test
const arr = ['z', 'y', 'z'];
console.log(copyArr1(arr)); // ["z", "y", "z"]
console.log(copyArr2(arr)); // ["z", "y", "z"]

使用Array.from 方法将类似数组的对象转为数组。

const obj = { "0": "a", "1": "b", length: 2};
const arr = Array.from(obj);

// test
console.log(arr); //  ["a", "b"]

6、函数

1、立即执行函数可以写成箭头函数的形式。

(() => {
    console.log('this is a good night.');
})();

2、在需要使用函数表达式的场合,尽量用箭头函数代替。因为这样可以更简洁,而且绑定了this。

// bad
const sayHello = ['a', 'b', 'c'].map(function (w){
    return 'Hello, ' + w;
})

// good 
const sayHello2 = ['a', 'b', 'c'].map(w => {
    return 'Hello, ' + w;
});

// test
console.log(sayHello2); //  ["Hello, a", "Hello, b", "Hello, c"]

3、箭头函数取代Function.prototype.bind,不应再用self/_this/that绑定this.

// bad
const self = this;
const boundMethod = function(...params){
    return method.apply(self, params);
}

// acceptable
const boundMethod2 = method.bind(this);

// best
const boundMehod3 = (...params) => method.apply(this, params);

4、单行简单、无需复用的函数,建议采用箭头函数。如果函数体较为复杂,行数较多,还是应采用传统的函数写法。

5、所有配置项都应该集中在一个对象,放在到最后一个参数,布尔值不可以直接作为参数。

// bad
function divide(a, b, option = false){

}

// good
function divide(a, b, {option = false} = {}){

}

6、不要在函数体内使用arguments变量,使用rest运算符(...)代替。因为rest运算符可以显示声明我们想要获取的参数,而且arguments是一个类似数组的对象,而rest元素安抚可以提供一个真正的数组。

// bad
function f1(){
    const args = Array.prototype.slice.call(arguments);
    return args.join('-');
}

// good
function f2(...args){
    return args.join('-');
}

// test
console.log(f1(1, 2, 3)); // 1-2-3
console.log(f2(1, 2, 3)); // 1-2-3

扩展运算符用三个点号表示,功能是把数组或类数组对象展开成一系列用逗号隔开的值;而rest运算符也是三个点号,不过其功能与扩展运算符恰好相反,把逗号隔开的值序列组合成一个数组。rest是剩余的意思。

7、使用默认值语法设置函数参数的默认值。

// bad
function handleThings(opts){
    opts = opts || {};
    // ...
}

// good
function handleThings2(opts = {}){
    // ...
}

7、Map结构

Map和Object给人的感觉是同一个数据类型,但是在实际语义还需要更为准确的区分,原则如下:

  • 模拟实体对象时,使用Object;
  • 只需要k-v键值对数据结构时,使用Map;

Map拥有内建的遍历机制(实现了Iterator结构)

// Map拥有许多初始化方式,这里使用数组成员为两个长度的数组进行初始化(第一个元素为K,第二个元素为V)
let map = new Map([['k1', 'I'], ['k2', 'love'], ['k3', 'your']]);

// 遍历K
for(const key of map.keys()){
    console.log(key);
    // k1
    // k2
    // k3
}

// 遍历V
for (const value of map.values()) {
    console.log(value);
    // I
    // love
    // you
}

// 遍历K-V
for (const item of map.entries()) {
    console.log(item);
    // ['k1', 'I']
    // ['k2', 'love']
    // ['k3', 'your']
}

8、Class

1、总是用Class取代需要prototype的操作。因为Class的写法更简洁,更易于理解。接触过Java、C#比较多的朋友想必更喜欢这样的类语法方式。

// bad
function Queue1(contents = []){
    this._queue = [...contents];
}
Queue1.prototype.pop = function(){
    const value = this._queue[0];
    this._queue.splice(0, 1);
    return value;
}

// good
class Queue {
    constructor(contents = []){
        // 这里为什么不用this._queue = contents;呢?
        // 读过effective java的朋友想必知道一个规则:
        // 那就是在设计构造函数时,若传入的参数中有可变类型(对象、数组),
        // 则构造函数内部接收此参数时应使用这个对象的拷贝。
        // 这样可以避免外部参数对象的更改影响到类本身的实例。
        // 因此,此处的contents需要拷贝一个复制在进行赋值。
        this._queue = [...contents];
    }
    pop() {
        const value = this._queue[0];
        this._queue.splice(0, 1);
        return value;
    }
}

// test
q = new Queue([1, 2, 3]);

console.log(q.pop()); // 1
console.log(q.pop()); // 2
console.log(q.pop()); // 3
console.log(q.pop()); // undefined

2、使用extends实现继承,因为这样可以更简单,不存在破坏instanceof运算的危险。

// Queue为上一个例子的类
class PeekQueue extends Queue{
    // ...
}

9、模块

1、Module语法是js模块的标准写法,要坚持使用这种写法。使用import取代require。

// bad
const ma = require('moduleA');
const f1 = ma.f1;
const f2 = ma.f2;

// good
import {f1, f2} from 'moduleA';

2、使用export取代module.export

// bad
module.exports = SomeObj;

// good
export default SomeObj;

3、如果模块只有一个输出值,就使用 export default; 若有镀铬,就不要使用 export default, 不要同时使用 export default 和 普通的 export,虽然规则上允许此种编写代码的方式。

4、不要在模块中使用通配符,因为这样可以确保模块中有一个默认输出:export default。

// bad
import * as myObject './someModule';

// good
import myObject from './someModule';

5、如果模块默认输出一个函数,函数的首字母应该小写。

function someFunction(){
     // ...
 }
 export default someFunction;

6、 如果模块默认输出一个对象,对象名的首字母应该大写。

const someObj = {
    // ...
}
export default SomeObj;

10、ESLint

前面说了那么多规则,其实只是规则范本的冰山一角,真正想要写出格式优美、符合主流厂商规范的代码,仅仅靠我们的自觉是不够的。

有没有什么类似软件编译工具检查代码正确性来检查代码编写规范的软件呢,答案是有的。

ESLint就是这样的一款检查工具。可以用于保证写出语法正确、风格统一的代码。

以下是安装ESLink的教程(确保您的环境已经安装了npm),当然,如果您使用一些脚手架工具(例如@vue-cli)等方式生成的项目,那么这样的项目都是提供了可选的eslint插件的。当前版本为: v6.6.0。该版本的eslint提供了更为简单的配置方式,可以参考https://eslint.bootcss.com/docs/user-guide/getting-started/进行配置。以下是一个粗略的配置步骤

1、安装所需插件

$ npm install eslint -g

2、生成package.json文件

$ npm init

该方法会在当前目录生成package.json文件,该文件类似于环境的说明文件。

3、生成eslint配置文件

$ eslint --init

该命令会询问你使用哪种类型的配置(通过上下箭头选取)

  • 推荐选用json或者JavaScript类型,我这里使用的是JavaScript类型的配置文件
  • style guide选用airbnb。

其他的选项根据你的需要进行选取即可。完成选择之后,会自动下载所需要的依赖包。

生成的配置文件内容大致如下:

module.exports = {
  env: {
    browser: true,
    es6: true,
  },
  extends: [
    'airbnb-base',
  ],
  globals: {
    Atomics: 'readonly',
    SharedArrayBuffer: 'readonly',
  },
  parserOptions: {
    ecmaVersion: 2018,
    sourceType: 'module',
  },
  rules: {
  },
};

我们在该配置文件中可以修改验证规则,具体的内容同样参考上面给出的链接。

4、在当前目录下,创建一个js文件

// index.js
var unused = '灰与幻想的格林姆迦尔';

function hello(){
    var message = "Hello, zhaoyi!";
    alert(message);
}
  
hello();

5、通过eslint验证代码编写正确性

$ eslint index.js

 

 1:12  error    Expected linebreaks to be 'LF' but found 'CRLF'  linebreak-style

  2:1   error    Unexpected var, use let or const instead         no-var

  2:5   error    'unused' is assigned a value but never used      no-unused-vars

  2:27  error    Expected linebreaks to be 'LF' but found 'CRLF'  linebreak-style

  3:1   error    Expected linebreaks to be 'LF' but found 'CRLF'  linebreak-style

  4:17  error    Missing space before opening brace               space-before-blocks

  4:18  error    Expected linebreaks to be 'LF' but found 'CRLF'  linebreak-style

  5:1   error    Expected indentation of 2 spaces but found 4     indent

  5:5   error    Unexpected var, use let or const instead         no-var

  5:19  error    Strings must use singlequote                     quotes

  5:36  error    Expected linebreaks to be 'LF' but found 'CRLF'  linebreak-style

  6:1   error    Expected indentation of 2 spaces but found 4     indent

  6:5   warning  Unexpected alert                                 no-alert

  6:20  error    Expected linebreaks to be 'LF' but found 'CRLF'  linebreak-style

  7:2   error    Expected linebreaks to be 'LF' but found 'CRLF'  linebreak-style

  8:1   error    Trailing spaces not allowed                      no-trailing-spaces

  8:3   error    Expected linebreaks to be 'LF' but found 'CRLF'  linebreak-style

  9:9   error    Trailing spaces not allowed                      no-trailing-spaces

  9:10  error    Newline required at end of file but not found    eol-last

其中,有一种错误其实是因为git文件格式转化的问题:

... linebreak-style

我们可以在配置文件中移除该检测:在rules下添加'linebreak-style': [0, 'error', 'windows'].

rules: {
    'linebreak-style': [0, 'error', 'windows']
  }

继续运行检测命令,可以看到如下的输出:

2:1   error    Unexpected var, use let or const instead      no-var

2:5   error    'unused' is assigned a value but never used   no-unused-vars

5:1   error    Expected indentation of 2 spaces but found 4  indent

5:5   error    Unexpected var, use let or const instead      no-var

5:19  error    Strings must use singlequote                  quotes

6:1   error    Expected indentation of 2 spaces but found 4  indent

6:5   warning  Unexpected alert                              no-alert

8:1   error    Trailing spaces not allowed                   no-trailing-spaces

9:9   error    Trailing spaces not allowed                   no-trailing-spaces

可以看到,我们许多不规范的操作都会警告了。比如缩进不要用四空格(其实是我们的编译器自带,而且我们习惯了的),不要加多余的空格,以及删掉没有使用过的声明变量,不推荐使用var类型等等。

如果觉得合情合理,那么遵循之;如果觉得缩进这些不符合自己的习惯,也可以通过配置文件进行关闭/修改等操作达到预期的效果。

以上就是详解JS ES6编码规范的详细内容,更多关于JS ES6编码规范的资料请关注三水点靠木其它相关文章!

Javascript 相关文章推荐
javascript 面向对象编程基础 多态
Aug 21 Javascript
扩展jquery实现客户端表格的分页、排序功能代码
Mar 16 Javascript
利用js的Node遍历找到repeater的一个字段实例介绍
Apr 25 Javascript
javascript将浮点数转换成整数的三个方法
Jun 23 Javascript
一个简单的jQuery插件ajaxfileupload.js实现ajax上传文件例子
Jun 26 Javascript
动态生成的DOM不会触发onclick事件的原因及解决方法
Aug 06 Javascript
bootstrap输入框组使用方法
Feb 07 Javascript
javascript中数组的常用算法深入分析
Mar 12 Javascript
JS校验与最终登陆界面功能完整示例
Jan 13 Javascript
javascript设计模式 ? 简单工厂模式原理与应用实例分析
Apr 09 Javascript
Electron整合React使用搭建开发环境的步骤详解
Jun 07 Javascript
jquery实现有过渡效果的tab切换
Jul 17 jQuery
html5中sharedWorker实现多页面通信的示例代码
May 07 #Javascript
详解如何使用Node.js实现热重载页面
May 06 #Javascript
关于Vue Router的10条高级技巧总结
May 06 #Vue.js
在JavaScript中如何使用宏详解
May 06 #Javascript
如何用JS实现简单的数据监听
May 06 #Javascript
详解TS数字分隔符和更严格的类属性检查
May 06 #Javascript
JS中一些高效的魔法运算符总结
May 06 #Javascript
You might like
html中select语句读取mysql表中内容
2006/10/09 PHP
PHP脚本中include文件出错解决方法
2008/11/20 PHP
php 结果集的分页实现代码
2009/03/10 PHP
php 修改zen-cart下单和付款流程以防止漏单
2010/03/08 PHP
让textarea控件的滚动条怎是位与最下方
2007/04/20 Javascript
javascript 伪数组实现方法
2010/10/11 Javascript
用Jquery.load载入页面实现局部刷新
2014/01/22 Javascript
js中this的用法实例分析
2015/01/10 Javascript
JavaScript去除数组里重复值的方法
2015/07/13 Javascript
JavaScript实现上下浮动的窗口效果代码
2015/10/12 Javascript
不得不看之JavaScript构造函数及new运算符
2017/08/21 Javascript
Vue中ref和$refs的介绍以及使用方法示例
2021/01/11 Vue.js
Tensorflow 自带可视化Tensorboard使用方法(附项目代码)
2018/02/10 Python
python面试题小结附答案实例代码
2019/04/11 Python
python pandas写入excel文件的方法示例
2019/06/25 Python
Django model select的多种用法详解
2019/07/16 Python
tornado+celery的简单使用详解
2019/12/21 Python
python3实现网页版raspberry pi(树莓派)小车控制
2020/02/12 Python
Python接口测试文件上传实例解析
2020/05/22 Python
python tkiner实现 一个小小的图片翻页功能的示例代码
2020/06/24 Python
python 写一个水果忍者游戏
2021/01/13 Python
Python列表的深复制和浅复制示例详解
2021/02/12 Python
详解H5 活动页之移动端 REM 布局适配方法
2017/12/07 HTML / CSS
国际奢侈品品牌童装购物网站:Designer Childrenswear
2019/05/08 全球购物
德国前卫设计师时装在线商店:Luxury Loft
2019/11/04 全球购物
FirstCry阿联酋儿童和婴儿产品网上购物:FirstCry.ae
2021/02/22 全球购物
学前班教师的自我鉴定
2013/12/05 职场文书
经济信息系毕业生自荐信范文
2014/03/15 职场文书
技术负责人任命书
2014/06/05 职场文书
实训报告范文大全
2014/11/04 职场文书
学前班幼儿评语大全
2014/12/29 职场文书
离职感谢信怎么写
2015/01/22 职场文书
小学运动会入场词
2015/07/18 职场文书
小学语文教师研修日志
2015/11/13 职场文书
css position fixed 左右双定位的实现代码
2021/04/29 HTML / CSS
面试中老生常谈的MySQL问答集锦夯实基础
2022/03/13 MySQL