本文转自:http://es6.ruanyifeng.com/#docs/style

编程风格

  1. 块级作用域
  2. 字符串
  3. 解构赋值
  4. 对象
  5. 数组
  6. 函数
  7. Map结构
  8. Class
  9. 模块
  10. ESLint的使用

本章探讨如何将ES6的新语法,运用到编码实践之中,与传统的JavaScript语法结合在一起,写出合理的、易于阅读和维护的代码。

多家公司和组织已经公开了它们的风格规范,具体可参阅jscs.info,下面的内容主要参考了Airbnb的JavaScript风格规范。

块级作用域

(1)let 取代 var

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

'use strict';if (true) { let x = 'hello'; } for (let i = 0; i < 10; i++) { console.log(i); } 

上面代码如果用var替代let,实际上就声明了两个全局变量,这显然不是本意。变量应该只在其声明的代码块内有效,var命令做不到这一点。

var命令存在变量提升效用,let命令没有这个问题。

'use strict';if(true) { console.log(x); // ReferenceError let x = 'hello'; } 

上面代码如果使用var替代letconsole.log那一行就不会报错,而是会输出undefined,因为变量声明提升到代码块的头部。这违反了变量先声明后使用的原则。

所以,建议不再使用var命令,而是使用let命令取代。

(2)全局常量和线程安全

letconst之间,建议优先使用const,尤其是在全局环境,不应该设置变量,只应设置常量。

const优于let有几个原因。一个是const可以提醒阅读程序的人,这个变量不应该改变;另一个是const比较符合函数式编程思想,运算不改变值,只是新建值,而且这样也有利于将来的分布式运算;最后一个原因是 JavaScript 编译器会对const进行优化,所以多使用const,有利于提供程序的运行效率,也就是说letconst的本质区别,其实是编译器内部的处理不同。

// 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]; 

const声明常量还有两个好处,一是阅读代码的人立刻会意识到不应该修改这个值,二是防止了无意间修改变量值所导致的错误。

所有的函数都应该设置为常量。

长远来看,JavaScript可能会有多线程的实现(比如Intel的River Trail那一类的项目),这时let表示的变量,只应出现在单线程运行的代码中,不能是多线程共享的,这样有利于保证线程安全。

字符串

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

// bad
const a = "foobar"; const b = 'foo' + a + 'bar';  // acceptable const c = `foobar`;  // good const a = 'foobar'; const b = `foo${a}bar`; const c = 'foobar'; 

解构赋值

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

const arr = [1, 2, 3, 4];  // bad const first = arr[0]; const second = arr[1];  // good const [first, second] = arr; 

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

// bad
function getFullName(user) { const firstName = user.firstName; const lastName = user.lastName; }  // good function getFullName(obj) { const { firstName, lastName } = obj; }  // best function getFullName({ firstName, lastName }) { } 

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

// bad
function processInput(input) { return [left, right, top, bottom]; }  // good function processInput(input) { return { left, right, top, bottom }; } const { left, right } = processInput(input); 

对象

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

// bad
const a = { k1: v1, k2: v2, }; const b = { k1: v1, k2: v2 };  // good const a = { k1: v1, k2: v2 }; const b = { k1: v1, k2: v2, }; 

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

// bad
const a = {}; a.x = 3;  // if reshape unavoidable const a = {}; Object.assign(a, { x: 3 });  // good const a = { x: null }; a.x = 3; 

如果对象的属性名是动态的,可以在创造对象的时候,使用属性表达式定义。

// bad
const obj = {id: 5, name: 'San Francisco', }; obj[getKey('enabled')] = true;  // good const obj = { id: 5, name: 'San Francisco', [getKey('enabled')]: true, }; 

上面代码中,对象obj的最后一个属性名,需要计算得到。这时最好采用属性表达式,在新建obj的时候,将该属性与其他属性定义在一起。这样一来,所有属性就在一个地方定义了。

另外,对象的属性和方法,尽量采用简洁表达法,这样易于描述和书写。

var ref = 'some value';  // bad const atom = { ref: ref, value: 1, addValue: function (value) { return atom.value + value; }, };  // good const atom = { ref, value: 1, addValue(value) { return atom.value + value; }, }; 

数组

使用扩展运算符(...)拷贝数组。

// bad
const len = items.length; const itemsCopy = []; let i; for (i = 0; i < len; i++) { itemsCopy[i] = items[i]; }  // good const itemsCopy = [...items]; 

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

const foo = document.querySelectorAll('.foo'); const nodes = Array.from(foo); 

函数

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

(() => { console.log('Welcome to the Internet.'); })(); 

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

// bad
[1, 2, 3].map(function (x) { return x * x; });  // good [1, 2, 3].map((x) => { return x * x; });  // best [1, 2, 3].map(x => x * x); 

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

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

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

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

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

不要在函数体内使用arguments变量,使用rest运算符(...)代替。因为rest运算符显式表明你想要获取参数,而且arguments是一个类似数组的对象,而rest运算符可以提供一个真正的数组。

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

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

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

Map结构

注意区分Object和Map,只有模拟现实世界的实体对象时,才使用Object。如果只是需要key: value的数据结构,使用Map结构。因为Map有内建的遍历机制。

let map = new Map(arr); for (let key of map.keys()) { console.log(key); } for (let value of map.values()) { console.log(value); } for (let item of map.entries()) { console.log(item[0], item[1]); } 

Class

总是用Class,取代需要prototype的操作。因为Class的写法更简洁,更易于理解。

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

使用extends实现继承,因为这样更简单,不会有破坏instanceof运算的危险。

// bad
const inherits = require('inherits'); function PeekableQueue(contents) { Queue.apply(this, contents); } inherits(PeekableQueue, Queue); PeekableQueue.prototype.peek = function() { return this._queue[0]; }  // good class PeekableQueue extends Queue { peek() { return this._queue[0]; } } 

模块

首先,Module语法是JavaScript模块的标准写法,坚持使用这种写法。使用import取代require

// bad
const moduleA = require('moduleA'); const func1 = moduleA.func1; const func2 = moduleA.func2;  // good import { func1, func2 } from 'moduleA'; 

使用export取代module.exports

// commonJS的写法
var React = require('react'); var Breadcrumbs = React.createClass({ render() { return <nav />; } }); module.exports = Breadcrumbs;  // ES6的写法 import React from 'react'; const Breadcrumbs = React.createClass({ render() { return <nav />; } }); export default Breadcrumbs 

如果模块只有一个输出值,就使用export default,如果模块有多个输出值,就不使用export default,不要export default与普通的export同时使用。

不要在模块输入中使用通配符。因为这样可以确保你的模块之中,有一个默认输出(export default)。

// bad
import * as myObject './importModule';  // good import myObject from './importModule'; 

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

function makeStyleGuide() { } export default makeStyleGuide; 

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

const StyleGuide = {es6: { } }; export default StyleGuide; 

ESLint的使用

ESLint是一个语法规则和代码风格的检查工具,可以用来保证写出语法正确、风格统一的代码。

首先,安装ESLint。

$ npm i -g eslint

然后,安装Airbnb语法规则。

$ npm i -g eslint-config-airbnb

最后,在项目的根目录下新建一个.eslintrc文件,配置ESLint。

{"extends": "eslint-config-airbnb" } 

现在就可以检查,当前项目的代码是否符合预设的规则。

index.js文件的代码如下。

var unusued = 'I have no purpose!'; function greet() { var message = 'Hello, World!'; alert(message); } greet(); 

使用ESLint检查这个文件。

$ eslint index.js
index.js1:5 error unusued is defined but never used no-unused-vars 4:5 error Expected indentation of 2 characters but found 4 indent 5:5 error Expected indentation of 2 characters but found 4 indent ✖ 3 problems (3 errors, 0 warnings) 

上面代码说明,原文件有三个错误,一个是定义了变量,却没有使用,另外两个是行首缩进为4个空格,而不是规定的2个空格。

转载于:https://www.cnblogs.com/freeliver54/p/6807930.html

[转]ECMAScript 6 入门 -编程风格相关推荐

  1. 【ES6】ES6编程规范 编程风格

    [ES6]ES6编程规范 编程风格 一.定义变量的规范 二.字符串 三.对象 四.数组 五.函数 查看更多ES6教学文章: 参考文献 引言:这是ES6系列教学的最后一篇.我们讲解一下ES6编程的规范. ...

  2. 【黑马程序员 C++教程从0到1入门编程】【笔记1】数据类型、运算符、程序流程结构、数组、函数、指针、结构体

    黑马程序员匠心之作|C++教程从0到1入门编程,学习编程不再难 文章目录 1.C++初识 1.1 第一个c++程序 1.2 注释 1.3 变量 1.4 常量 1.5 关键字 1.6 标识符命名规则 2 ...

  3. 阮一峰 《ECMAScript 6 入门》:let 和 const 命令

    以下内容全文出自 阮一峰的书: <ECMAScript 6 入门> 电子版地址:ES 6标准入门(第3版) let 命令 基本用法 ES6 新增了let命令,用来声明变量.它的用法类似于v ...

  4. 零基础小白应该怎么入门编程开发

    最近,在交流群里经常有苦逼小白问怎样学编程,对编程有兴趣但无从下手,这是个庞大到让大神们"无言以对"的命题.在知乎.CSDN等论坛上,许多同行也对此类问题进行了探讨,小编就其中认可 ...

  5. 零基础如何入门编程开发?

    随着信息技术的快速发展,编程已经成为一个越来越重要的技能.那么,我们该如何入门编程呢?欢迎大家积极讨论 一.自学编程需要注意什么? 1. 先培养兴趣 其实自学编程不是那么难,只要是理工科生.逻辑思维好 ...

  6. 我们该如何入门编程呢

    随着信息技术的快速发展,编程已经成为一个越来越重要的技能.那么,我们该如何入门编程呢?选择编程语言:选择一种编程语言,并了解其基本语法和概念.Python.Java.C++等是比较流行的编程语言,也是 ...

  7. c++资料匠心精作C++从0到1入门编程(三)- c++核心(基于STL的泛式编程)

    目录 C++提高编程 1 模板 1.1 模板的概念 1.2 函数模板 1.2.1 函数模板语法 1.2.2 函数模板注意事项 1.2.3 函数模板案例 1.2.4 普通函数与函数模板的区别 1.2.5 ...

  8. day01--java基础编程:计算机基础知识 ,java语言概述,java开发环境搭建,eclipse概述,创建简单java项目,JDK JRE JVM的关系,java开发中的命名规范,编程风格

    1 Day01–Java开发环境+HelloWorld 1.1 计算机基础知识 资料下载网址:刘沛霞 18600949004 code.tarena.com.cn tarenacode code_20 ...

  9. python 判断中文标点符号_Python入门编程题库27--生成随机密码

    一.题目 请编写程序,生成随机密码.具体要求如下: (1)使用 random 库,采用 0x1010 作为随机数种子. (2)密码 有s中的字符组成. (3)每个密码长度固定为 10 个字符. (4) ...

最新文章

  1. sun.misc.BASE64Encoder找不到jar包的解决方法
  2. woff, 在网页中嵌入任意字体的解决方案
  3. 魔兽世界怀旧服最新服务器开发时间,怀旧服开70最新消息汇总 魔兽怀旧服TBC开放时间几个阶段?...
  4. 摄像头poe供电原理_弱电知识之六:跟我学做监控,认识POE交换机与POE监控摄像头...
  5. php自动维护,完全禁用关闭Windows Server 2012R2自动维护功能禁用WIN2012R2自动维护
  6. OAuth与Spring Security
  7. etmvc mysql乱码_Etmvc学习文档
  8. 编译Bootstrap3
  9. JVM 调优一个月,性能提升了 400 倍!
  10. mysql数据库105页_MySQL数据库的常见操作
  11. 读《UNIX 编程艺术》
  12. 利用html模板发送邮件
  13. 计算机算平方根原理,算术平方根与计算器
  14. 目前1KB文件夹快捷方式病毒扫清方法
  15. xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
  16. 2020-10-19 Nvidia与vGPU
  17. SAR成像系列:【11】干涉合成孔径雷达(干涉SAR,Interferometric SAR,InSAR)
  18. Java 中this和super的用法总结
  19. 第五期_信息收集《Metasploit Unleashed Simplified Chinese version(Metasploit官方文档教程中文版)》
  20. 113.网络安全渗透测试—[权限提升篇11]—[Windows 2003 Mysql MOF提权]

热门文章

  1. Velodyne收购高清地图公司 将研发更安全的ADAS系统
  2. 八个最好的开源机器学习框架和库
  3. CreateEvent创建事件对象
  4. mysql如何进行压测_详解MySQL如何按表创建千万级的压测数据
  5. 单体预聚合的目的是什么_聚合物在加工过程中降解可能性分析与预防
  6. 前端实习生笔试_一道来自美图的实习生前端笔试算法题
  7. jvm 9种垃圾收集器
  8. 026_html表单
  9. 上传文件 微信小程序input_快速上手微信小程序UI框架
  10. centos6 配置ip、服务