Js ES6编码规范

时间: 2019-10-28阅读: 130标签: 规范

简介

本章节讨论使用ES6编码风格到代码中需要注意的点。通过记住这些关键点,可以让我们写出更优美的、可读性更强的JavaScript E6风格的代码。


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类型等等。

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

参考:ES6标准入门(第三版)——阮一峰 

 

吐血推荐

1.站长广告联盟: 整理了目前主流的广告联盟平台,如果你有流量,可以作为参考选择适合你的平台点击进入...

2.休闲娱乐: 网页游戏  直播/交友   H5游戏

链接: http://www.fly63.com/article/detial/6154

分享一份大佬的MySQL数据库设计规范,值得收藏

MySQL数据库与 Oracle、 SQL Server 等数据库相比,有其内核上的优势与劣势。我们在使用MySQL数据库的时候需要遵循一定规范,扬长避短。无意中从github上看到一个大佬的MySQL数据库设计规范

CSS的BEM规范学习

块中的子元素是块的子元素,并且子元素的子元素在 bem 里也被认为是块的直接子元素。一个块中元素的类名必须用父级块的名称作为前缀。如上面的例子,li.item 是列表的一个子元素

Web前端开发规范手册

文件命名规则:文件名称统一用小写的英文字母、数字和下划线的组合。引文件统一使用index.htm index.html index.asp文件名(小写),图片的名称分为头尾两部分,用下划线隔开,头部分表示此图片的大类性质

为什么有的编程规范要求用 void 0 代替 undefined?

Undefined 类型表示未定义,它的类型只有一个值,就是 undefined。任何变量在被赋值前它的值都是 undefined,但是在 JavaScript 引擎中,undefined 是一个变量而非关键字。

CSS的书写规范和顺序

关于CSS的书写规范和顺序,是大部分前端er都必须要攻克的一门关卡,如果没有按照良好的CSS书写规范来写CSS代码,会影响代码的阅读体验。这里总结了一个CSS书写规范、CSS书写顺序供大家参考

实际项目中用Redis要注意哪些规范?

Redis功能强大,数据类型丰富,再快的系统,也经不住疯狂的滥用。通过禁用部分高风险功能,并挂上开发的枷锁,业务更能够以简洁、通用的思想去考虑问题,而不是绑定在某种实现上。

前端标准规范

总体原则:极简、极快、解耦,主要适用范围:vue 单页项目+;关于图片:少量直接放到本页面文件下(资源集中,互不影响),有两个页面以上公用则抽离放到 img 文件夹下(降低层级),assets 下的 img 主要放 favicon.png、pwa等全局图片

HTML 规范未来还需要哪些新内容?

HTML5 规范在 2014 年正式发布。时至今日,虽然这一规范已经引入了许多新的 API、功能和改进,但许多开发人员已经在展望下一代 HTML 规范了。有些人还是不知道 HTML 标准是怎样制定出来的。具体来说,一些组织提出自己的模式和协议

一份完整的MySQL开发规范,进大厂必看!

所有数据库对象名称必须使用小写字母并用下划线分割;所有数据库对象名称禁止使用mysql保留关键字(如果表名中包含关键字查询时,需要将其用单引号括起来);数据库对象的命名要能做到见名识意

Css中bem书写规范

bem是基于组件的web开发方法。其思想是将用户界面分隔为独立的块,从而使开发复杂的UI界面变得更简单和快,且不需要粘贴复制便可复用现有代码。BEM由Block、Element、Modifier组成。选择器里用以下连接符扩展他们的关系:

fly63.com版权所有,内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权,请与小编联系!情况属实本人将予以删除!

广告赞助文章投稿关于web前端网站点搜索站长推荐网站地图站长QQ:522607023

小程序专栏: 土味情话心理测试脑筋急转弯幽默笑话段子句子语录成语大全