传值

所有需要传值到页面的,都需要进行判空

  1. if(value.hour !=undefined && value.minute !=undefined){
  2. tideTimeArr.push(value.hour+':'+value.minute)
  3. }else{
  4. tideTimeArr.push("")
  5. }
  6. if(data.WINDPWR == undefined){
  7. data.WINDPWR=""
  8. }

引用

constlet 都是块级作用域,var 是函数级作用域

  • 对所有引用都使用 const,不要使用 var | // badvar a = 1var b = 2// goodconst a = 1const b = 2 | | :—- |

  • 如果引用是可变动的,则使用 let | // badvar count = 1if (count < 10) { count += 1}// goodlet count = 1if (count < 10) { count += 1} | | :—- |

对象

  • 请使用字面量值创建对象 | // badconst a = new Object{}// goodconst a = {} | | :—- |

  • 别使用保留字作为对象的键值,这样在 IE8 下不会运行 | // badconst a = { default: {}, // default 是保留字 common: {}}// goodconst a = { defaults: {}, common: {}} | | :—- |

  • 请使用对象方法的简写方式 | // badconst item = { value: 1, addValue: function (val) { return item.value + val }}// goodconst item = { value: 1, addValue(val) { return item.value + val }} | | :—- |

  • 请使用对象属性值的简写方式 | const job = ‘FrontEnd’// badconst item = { job: job}// goodconst item = { job} | | :—- |

  • 对象属性值的简写方式要和声明式的方式分组 | const job = ‘FrontEnd’const department = ‘JDC’// badconst item = { sex: ‘male’, job, age: 25, department}// goodconst item = { job, department, sex: ‘male’, age: 25} | | :—- |

数组

  • 请使用字面量值创建数组 | // badconst items = new Array()// goodconst items = [] | | :—- |

  • 向数组中添加元素时,请使用 push 方法 | const items = []// baditems[items.length] = ‘test’// gooditems.push(‘test’) | | :—- |

  • 使用拓展运算符 ... 复制数组 | // badconst items = []const itemsCopy = []const len = items.lengthlet i// badfor (i = 0; i < len; i++) { itemsCopy[i] = items[i]}// gooditemsCopy = […items] | | :—- |

  • 使用数组的 map 等方法时,请使用 return 声明,如果是单一声明语句的情况,可省略 return | // good[1, 2, 3].map(x => { const y = x + 1 return x * y})
    // good[1, 2, 3].map(x => x + 1)
    // badconst flat = {}[[0, 1], [2, 3], [4, 5]].reduce((memo, item, index) => { const flatten = memo.concat(item) flat[index] = flatten})
    // goodconst flat = {}[[0, 1], [2, 3], [4, 5]].reduce((memo, item, index) => { const flatten = memo.concat(item) flat[index] = flatten return flatten})
    // badinbox.filter((msg) => { const { subject, author } = msg if (subject === ‘Mockingbird’) { return author === ‘Harper Lee’ } else { return false }})
    // goodinbox.filter((msg) => { const { subject, author } = msg if (subject === ‘Mockingbird’) { return author === ‘Harper Lee’ }
    return false}) | | :—- |

解构赋值

  • 当需要使用对象的多个属性时,请使用解构赋值 | // badfunction getFullName (user) { const firstName = user.firstName const lastName = user.lastName return ${firstName} ${lastName}}// goodfunction getFullName (user) { const { firstName, lastName } = user return ${firstName} ${lastName}}// betterfunction getFullName ({ firstName, lastName }) { return ${firstName} ${lastName}} | | :—- |

  • 当需要使用数组的多个值时,请同样使用解构赋值 | const arr = [1, 2, 3, 4]
    // badconst first = arr[0]const second = arr[1]
    // goodconst [first, second] = arr | | :—- |

  • 函数需要回传多个值时,请使用对象的解构,而不是数组的解构 | // badfunction doSomething () { return [top, right, bottom, left]}// 如果是数组解构,那么在调用时就需要考虑数据的顺序const [top, xx, xxx, left] = doSomething()// goodfunction doSomething () { return { top, right, bottom, left }}// 此时不需要考虑数据的顺序const { top, left } = doSomething() | | :—- |

字符串

  • 字符串统一使用单引号的形式 '' | // badconst department = “JDC”// goodconst department = ‘JDC’ | | :—- |

  • 字符串太长的时候,请不要使用字符串连接符换行 \,而是使用 + | const str = ‘凹凸实验室 凹凸实验室 凹凸实验室’ + ‘凹凸实验室 凹凸实验室 凹凸实验室’ + ‘凹凸实验室 凹凸实验室’ | | :—- |

  • 程序化生成字符串时,请使用模板字符串 | const test = ‘test’// badconst str = [‘a’, ‘b’, test].join()// badconst str = ‘a’ + ‘b’ + test// goodconst str = ab${test} | | :—- |

函数

  • 请使用函数声明,而不是函数表达式 | // badconst foo = function () { // do something}// goodfunction foo () { // do something} | | :—- |

  • 不要在非函数代码块中声明函数 | // badif (isUse) { function test () { // do something }}// goodlet testif (isUse) { test = () => { // do something }} | | :—- |

  • 不要使用 arguments,可以选择使用 ...

    arguments 只是一个类数组,而 ... 是一个真正的数组

原型

  • 使用 class,避免直接操作 prototype | // badfunction Queue (contents = []) { this._queue = [..contents]}Queue.prototype.pop = function () { const value = this._queue[0] this._queue.splice(0, 1) return value}// goodclass Queue { constructor (contents = []) { this._queue = […contents] } pop () { const value = this._queue[0] this._queue.splice(0, 1) return value }} | | :—- |

模块

  • 使用标准的 ES6 模块语法 importexport | // badconst util = require(‘./util’)module.exports = util// goodimport Util from ‘./util’export default Util// betterimport { Util } from ‘./util’export default Util | | :—- |

  • 不要使用 import 的通配符 *,这样可以确保你只有一个默认的 export | // badimport * as Util from ‘./util’// goodimport Util from ‘./util’ | | :—- |

迭代器

  • 不要使用 iterators | const numbers = [1, 2, 3, 4, 5]// badlet sum = 0for (let num of numbers) { sum += num}// goodlet sum = 0numbers.forEach(num => sum += num)// betterconst sum = numbers.reduce((total, num) => total + num, 0) | | :—- |

对象属性

  • 使用 . 来访问对象属性 | const joke = { name: ‘haha’, age: 28}// badconst name = joke[‘name’]// goodconst name = joke.name | | :—- |

变量声明

  • 声明变量时,请使用 constlet 关键字,如果没有写关键字,变量就会暴露在全局上下文中,这样很可能会和现有变量冲突,另外,也很难明确该变量的作用域是什么。这里推荐使用 const 来声明变量,我们需要避免全局命名空间的污染。 | // baddemo = new Demo()// goodconst demo = new Demo() | | :—- |

  • 将所有的 constlet 分组 | // badlet aconst blet cconst dlet e// goodconst bconst dlet alet clet e | | :—- |

Hoisting

  • var 存在变量提升的情况,即 var 声明会被提升至该作用域的顶部,但是他们的赋值并不会。而 constlet 并不存在这种情况,他们被赋予了 Temporal Dead Zones, TDZ | function example () { console.log(notDefined) // => throws a ReferenceError}function example () { console.log(declareButNotAssigned) // => undefined var declaredButNotAssigned = true}function example () { let declaredButNotAssigned console.log(declaredButNotAssigned) // => undefined declaredButNotAssigned = true}function example () { console.log(declaredButNotAssigned) // => throws a ReferenceError console.log(typeof declaredButNotAssigned) // => throws a ReferenceError const declaredButNotAssigned = true} | | :—- |

  • 匿名函数的变量名会提升,但函数内容不会 | function example () { console.log(anonymous) // => undefined anonymous() var anonymous = function () { console.log(‘test’) }} | | :—- |

  • 命名的函数表达式的变量名会被提升,但函数名和函数函数内容并不会 | function example() { console.log(named) // => undefined named() // => TypeError named is not a function superPower() // => ReferenceError superPower is not defined var named = function superPower () { console.log(‘Flying’) }}function example() { console.log(named) // => undefined named() // => TypeError named is not a function var named = function named () { console.log(‘named’) }} | | :—- |

分号

  • 我们团队约定,再语句结束之后使用分号,以便使代码更清晰。
  • 下列关键字后必须有大括号(即使代码块的内容只有一行):if, else,for, while, do, switch, try, catch, finally, with。 | // goodconst test = ‘good’;(() => { const str = ‘hahaha’;})(); | | :—- |

  1. // not good
  2. if (condition)
  3. doSomething();
  4. // good
  5. if (condition) {
  6. doSomething();
  7. }

null

适用场景:

  • 初始化一个将来可能被赋值为对象的变量
  • 与已经初始化的变量做比较
  • 作为一个参数为对象的函数的调用传参
  • 作为一个返回对象的函数的返回值

不适用场景:

  • 不要用null来判断函数调用时有无传参
  • 不要与未初始化的变量做比较
  1. // not good
  2. function test(a, b) {
  3. if (b === null) {
  4. // not mean b is not supply
  5. ...
  6. }
  7. }
  8. let a;
  9. if (a === null) {
  10. ...
  11. }
  12. // good
  13. let a = null;
  14. if (a === null) {
  15. ...
  16. }

undefined

永远不要直接使用undefined进行变量判断;
使用typeof和字符串’undefined’对变量进行判断。

  1. // not good
  2. if (person === undefined) {
  3. ...
  4. }
  5. // good
  6. if (typeof person === 'undefined') {
  7. ...
  8. }

jshint

for-in里一定要有hasOwnProperty的判断;查找一个对象是否有某个属性,但是不会去查找它的原型链

  1. // good
  2. for (key in obj) {
  3. if (obj.hasOwnProperty(key)) {
  4. // be sure that obj[key] belongs to the object and was not inherited
  5. console.log(obj[key]);
  6. }
  7. }

不要在内置对象的原型上添加方法,如Array, Date;

  1. // not good
  2. Array.prototype.count = function(value) {
  3. return 4;
  4. };

不要在内层作用域的代码里声明了变量,之后却访问到了外层作用域的同名变量;

  1. // not good
  2. let x = 1;
  3. function test() {
  4. if (true) {
  5. let x = 0;
  6. }
  7. x += 1;
  8. }

变量不要先使用后声明;

  1. // not good
  2. function test() {
  3. console.log(x);
  4. let x = 1;
  5. }

不要在一句代码中单单使用构造函数,记得将其赋值给某个变量;

  1. // not good
  2. new Person();
  3. // good
  4. let person = new Person();

不要在一些不需要的地方加括号,例:delete(a.b);

  1. // not good
  2. delete(obj.attr);
  3. // good
  4. delete obj.attr;

数组中不要存在空元素;

  1. // not good
  2. let a = [1, , , 2, 3];

不要在循环内部声明函数;

  1. // not good
  2. let nums = [];
  3. for (let i = 0; i < 10; i++) {
  4. (function(i) {
  5. nums[i] = function(j) {
  6. return i + j;
  7. };
  8. }(i));
  9. }

不要使用未声明的变量;
不要声明了变量却不使用;
debugger不要出现在提交的代码里;

杂项

不要混用tab和space;
不要在一处使用多个tab或space;
对上下文this的引用只能使用’_this’来命名;
行尾不要有空白字符;
switch的falling through和no default的情况一定要有注释特别说明;
不允许有空的代码块。

  1. // not good
  2. let a = 1;
  3. function Person() {
  4. // not good
  5. let me = this;
  6. // good
  7. let _this = this;
  8. // good
  9. let that = this;
  10. // good
  11. let self = this;
  12. }
  13. // good
  14. switch (condition) {
  15. case 1:
  16. case 2:
  17. ...
  18. break;
  19. case 3:
  20. ...
  21. // why fall through
  22. case 4
  23. ...
  24. break;
  25. // why no default
  26. }
  27. // not good with empty block
  28. if (condition) {
  29. }