手记

如何培养良好的编码风格

前言: 虽然最近项目周期挺紧张的,晚上还是尽量挤出时间阅读《编写可维护的JavaScript》这本书籍。书籍总共分为三部分(编程风格,编程实践,自动化),本文是第一部分编程风格中我认为比较精彩的片段(检测值 && 格式化),也应用在了当前的项目中,整理出来跟大家分享,希望对大家在重构优化代码方面能够带来一定的帮助。

情景引入

在JavaScript中,我们常常会看到这种代码:变量和null的比较(这种写法很有问题),用来判断变量是否赋被赋予了一个合理的值。比如:

var Controller = {
    process: function (items) {
        if (item !== null) { // 不好的写法
            items.sort()
            items.forEach(item => {
                // 一些代码
            })
        }
    }
}

在这段代码中,process方法显然是希望items是一个数组,因为我们看到items拥有sort()和forEach().这段代码的意图非常明显;如果参数items不是一个数组,则停止接下来的操作。我们来分析一下,这种写法的问题在于和null比较并不能真正避免错误的发生。items的值可以是1,也可以是字符串,甚至可以是任意对象。这些值都和null不相等,进而会导致process()方法一旦执行到sort()时就会出错。

仅仅和null比较并不能提供足够的信息来判断后续的代码执行是否真的安全。好在JavaScript为我们提供了多种方法来检测变量的真实值。

检测值
一、检测原始值

在JavaScript中有5种原始类型:字符串,数字,布尔值,undefined,null

对于字符串,数字,布尔值,undefined,最佳选择是使用typeof运算符

示例代码:

// 检测字符串
if (typeof name === "string") {
  // 执行代码
}

// 检测数字
if (typeof count === "number") {
  // 一些代码
}

// 检测数字
if (typeof found === "boolean") {
  // 一些代码
}

// 检测undefined
if (typeof MyApp === "undefined") {
  // 一些代码
}

对于null

null,一般不应用于检测语句。正如上文情景引入中提到的,简单地和null比较通常不会包含足够的信息以判断值的类型是否合法。但有一个例外,如果所期望的值真的是null,则可以直接和null进行比较。 如果使用typeof运算符比较null,运行typeof null则返回'object',这是一种低效的判断null的方法。 如果你需要验证null,请直接使用恒等运算符(===)或非等运算符(!==) 示例代码: 输入框的值的判断

if (this.skuName !== null) {
  // 输入框有值才执行请求接口
  this.copySkuBlock()
} else {
  // 提示输入框要输入值
  this.$message({
    type: 'error',
    message: '请输入商品规格'
  })
}
二、检测引用值
在JavaScript钟有4种引用类型:Object, Array, Date, 和Error。

示例代码:

// 检测日期
if (value instanceof Date) {
  // 一些代码
}

// 检测正则表达式
if (value instanceof RegExp) {
  // 一些代码
}

// 检测Error
if (value instanceof Error) {
  // 一些代码
  throw value
}
三、检测函数

从技术上讲, JavaScript中的函数是引用类型,同样存在Function构造函数。由于instanceof运算符不能跨帧使用,typeof运算符则是检测函数的最佳选择。

示例代码:

function myFunc () {
// 不好的写法   不能跨帧使用,因为每个帧都有各自的Function构造函数
console.log(myFunc instanceof Function) // true
// 好的写法  能跨帧使用, 但只能在IE9+使用
console.log(typeof myFunc === "function") // true
}
四、检测数组

ES5将Array.isArray()的方法正式引入JavaScript,唯一的目的就是准确地检测一个值是否为数组,IE9+支持。

示例代码:

function isArray () {
  if (typeof Array.isArray === "function") {
    return Array.isArray(value)
  } else {
    return Object.prototype.toString.call(value) === "[object Array]"
  }
}
五、检测属性

另外一种用到null(以及undefined)的场景是当检测一个属性是否在对象中存在时。比如:

// 不好的写法: 和null比较
if (object[propertyName] !== null) {
  // 一些代码
}

判断对象中的属性是否存在最好的方法是使用in运算符。 in运算符仅仅会简单地判断属性是否存在,而不会去读属性的值。

示例代码:

A. 如果实例对象的属性存在、或者继承自对象的原型,in运算符都会返回true。比如:

if ("count" in object) {
  // 一些代码
}

B. 如果你只想检测实例对象的某个属性是否存在,则使用hasOwnProperty()方法,仅支持IE9+

if (object.hasOwnproperty("count")) {
  // 一些代码
}

因此,在判断实例对象的属性是否存在时,我更倾向于使用in运算符,只有在需要判断实例属性时才会用到hasOwnproperty,这样做可以避免很多bug。

格式化
一、基本格式化

1.变量和函数, 都用小驼峰式命名,变量用名词作前缀,函数用动词作前缀。

2.禁止使用特殊值underfined,可以有效地确保只在一种情况下typeof才会返回“underfined”

二、注释

1.使用注释的原则 当代码不够清晰时添加注释,而当代码很明了时不应当添加注释当代码不够清晰时添加注释,而当代码很明了时不应当添加注释

2.文档注释 开源项目中,强烈推荐用文档生成工具来生成文档注释,比如YUIDoc或JSDoc Toolkit。 在Google内部的很多开源项目JSDoc Toolkit的应用非常广泛,这两者的区别在于,YUIDoc可以同时支持文档注释中的HTML和Markdown格式,而JSDoc Toolkit 只支持HTML

三 语句和表达式

1.for循环

尽量用条件语句代替for循环中的continue,更加容易理解且不容易出错

示例代码

 // 不好的写法
  var values = [0, 1, 2, 3, 4, 5, 6],
    i,len
  for (i = 0, len = values.length; i < len; i++) {
    if (i === 2 ) {
    // 跳过本次循环
    continue
    }
    console.log('第' + i + '次循环')
  }
  // 好的写法
  var values = [0, 1, 2, 3, 4, 5, 6],
    i,len
  for (i = 0, len = values.length; i < len; i++) {
    if (i !== 2 ) {
    console.log('第' + i + '次循环')
    }
  }

2.for-in循环

for-in不仅遍历对象的实例属性,同样还会遍历从原型继承来的属性。因此,当遍历自定义对象的属性时,for-in遍历对象会遍历从原型继承来的属性,建议使用hasOwnProperty()方法来为for-in循环过滤出实例的属性

示例代码

// 好的写法
var prop
for (prop in object) {
   if (object.hasOwnProperty(prop)) {
      console.log('Property name is' + prop)
      console.log('Property value is' + object[prop])
   }
}

我推荐总是在for-in循环中使用hasOwnProperty(), 除非你想查找原型链,这时应当补充注释,比如:

// 好的写法
var prop
for (prop in object) {  // 包含对原型链的遍历
      console.log('Property name is' + prop)
      console.log('Property value is' + object[prop])
}

for-in循环是用来遍历对象的,禁止用来遍历数数组成员

示例代码

// 不好的写法
var values = [1, 2, 3],
    i
for (i in values) {
  console.log('Property name is' + i) // 0, 1, 2
  console.log('Property value is' + values[i]) // 1, 2, 3
}
四、变量、函数、运算符

1.变量声明

将局部变量的定义作为函数内第一条语句;所有的var语句合并为一个语句,每个变量的初始化独占一行。赋值运算符应当对齐。对于那些没有初始值的变量来说,它们应当出现在var语句的尾部。

示例代码

// 好的写法
function doSomething () {
   // 局部遍历的定义
   var value = 10,
       result = value + 10,
       i,
       len
   for (i = 0, len = items.length; i < len; i++) {
     doOtherSomething(items[i])
   }
}

严格模式
use strict 不仅适用于全局,也适用于局部,但是最好不要在全局作用域中使用“use strict”模式

示例代码

// 不好的写法 全局的严格模式
'use strict'
function doSomething () {
  // 一些代码
}
// 好的写法
(function () {
   'use strict'
   function doSomething () {
      // 一些代码
   }
   function doSomethingElse () {
     // 一些代码
   }
})

3.运算符

由于JavaScript具有强制类型转换机制的缘故,我们推荐不要使用==和!=,而是应当使用===和!==.

示例代码

// 不好的写法  字符串会被转为数字,然后再进行比较
console.log(5 == '5') // true
// 好的写法
console.log(5 === '5') // false

4.函数

eval()

通用原则:严禁使用function,并且只在别无他法时使用eval()

总结

that's all, 以上就是我目前所有的对第一部分编程风格的理解以及应用。觉得对你开发有帮助的可以点赞收藏一波,如果我哪里写错了,希望能指点出来。如果你有更好的想法或者建议,可以提出来在下方评论区与我交流。大家一起进步,共同成长。感谢[鞠躬]。

一起交流

ps: 提高自己,常与异性交朋友

作者:付出,原文地址

4人推荐
随时随地看视频
慕课网APP