美文网首页
写出更优秀的javascript代码

写出更优秀的javascript代码

作者: 朝西的生活 | 来源:发表于2019-01-28 14:46 被阅读0次

类型

  1. 在使用复合类型时需要注意其引用:
const foo = [1, 2];
const bar = foo;
bar[0] = 2;

console.log(foo, bar); // => [2, 2], [2, 2]

变量声明与赋值

  1. 使用let, const 代替 var:

let 和 const 是块级作用域(block-scoped), 而 var 是函数作用域(function-scoped), 使用let/const可以有效避免变量污染作用域

// bad
var a = 1;
var b = 2;

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

// bad
var count = 1;
if (true) {
  count += 1;
}

// good, use the let.
let count = 1;
if (true) {
  count += 1;
}
  1. 避免使用连续赋值
// bad
var a = 1, b, c;
// good
let a = 1;
let b;
let c;
  1. 不要使用链式赋值操作

可能污染全局变量

// bad
(function example() {
  // JavaScript interprets this as
  // let a = ( b = ( c = 1 ) );
  // The let keyword only applies to variable a; variables b and c become
  // global variables.
  let a = b = c = 1;
}());

console.log(a); // throws ReferenceError
console.log(b); // 1
console.log(c); // 1

// good
(function example() {
  let a = 1;
  let b = a;
  let c = a;
}());

console.log(a); // throws ReferenceError
console.log(b); // throws ReferenceError
console.log(c); // throws ReferenceError

// the same applies for `const`
  1. 在合适的位置分配变量
// bad - 当 'hasName' === 'test' 时,  `const name = getName`不必要
function checkName(hasName) {
  const name = getName();

  if (hasName === 'test') {
    return false;
  }

  if (name === 'test') {
    this.setName('');
    return false;
  }

  return name;
}

// good
function checkName(hasName) {
  if (hasName === 'test') {
    return false;
  }

  const name = getName();

  if (name === 'test') {
    this.setName('');
    return false;
  }

  return name;
}
  1. 避免使用自增/自减运算符

可能受到行尾自动插入分行的影响

  1. 变量声明就一定要使用

对象 & 数组

  1. 避免使用new 操作符创建对象/数组
// bad
const item = new Object();

// good
const item = {};
  1. 使用对象的计算属性来完成动态对象属性

在一个地方即可定义对象定义, 使代码更可读

function getKey(k) {
  return `a key named ${k}`;
}

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

// good
const obj = {
  id: 5,
  name: 'San Francisco',
  [getKey('enabled')]: true,
};
  1. 使用对象属性/方法的缩写
// bad
const atom = {
  value: 1,

  addValue: function (value) {
    return atom.value + value;
  },
};

// good
const atom = {
  value: 1,

  addValue(value) {
    return atom.value + value;
  },
};

const lukeSkywalker = 'Luke Skywalker';

// bad
const obj = {
  lukeSkywalker: lukeSkywalker,
};

// good
const obj = {
  lukeSkywalker,
};
  1. 将对象属性缩写与不缩写的属性分组区别开

可以更直观得看到缩写的属性

const anakinSkywalker = 'Anakin Skywalker';
const lukeSkywalker = 'Luke Skywalker';
// bad
const obj = {
   episodeOne: 1,
   twoJediWalkIntoACantina: 2,
   lukeSkywalker,
   episodeThree: 3,
   mayTheFourth: 4,
   anakinSkywalker,
 };

 // good
const obj = {
   lukeSkywalker,
   anakinSkywalker,
   episodeOne: 1,
   twoJediWalkIntoACantina: 2,
   episodeThree: 3,
   mayTheFourth: 4,
};
  1. 对象的属性只有在属性名不合法时使用引号, 且使用单引号

更易读, 并且更容易被js引擎优化

// bad
const bad = {
  'foo': 3,
  'bar': 4,
  'data-blah': 5,
};

// good
const good = {
  foo: 3,
  bar: 4,
  'data-blah': 5,
};
  1. 不要直接调用对象原型上面的方法, 如: hasOwnProperty, propertyIsEnumerable, isPrototypeOf:

避免调用冲突, { hasOwnProperty: false }, 并且调用对象可以是null (Object.create(null))

// bad
console.log(object.hasOwnProperty(key));

// good
console.log(Object.prototype.hasOwnProperty.call(object, key));

// best
const has = Object.prototype.hasOwnProperty; // cache the lookup once, in module scope.
/* or */
import has from 'has'; // https://www.npmjs.com/package/has
// ...
console.log(has.call(object, key));
  1. 使用...操作符浅拷贝对象/数组
// very bad
const original = { a: 1, b: 2 };
const copy = Object.assign(original, { c: 3 }); // 污染了原对象
delete copy.a; // so does this

// bad
const original = { a: 1, b: 2 };
const copy = Object.assign({}, original, { c: 3 }); // copy => { a: 1, b: 2, c: 3 }

// good
const original = { a: 1, b: 2 };
const copy = { ...original, c: 3 }; // copy => { a: 1, b: 2, c: 3 }

const { a, ...noA } = copy; // noA => { b: 2, c: 3 }
  1. 使用Array.from来将一个类数组的对象, 转化为真数组
const arrLike = { 0: 'foo', 1: 'bar', 2: 'baz', length: 3 };

// bad
const arr = Array.prototype.slice.call(arrLike);

// good
const arr = Array.from(arrLike);

解构

  1. 使用对象解构来操作多属性的对象 / 数组

可以避免声明许多临时变量

// bad
function getFullName(user) {
  const firstName = user.firstName;
  const lastName = user.lastName;

  return `${firstName} ${lastName}`;
}

// good
function getFullName(user) {
  const { firstName, lastName } = user;
  return `${firstName} ${lastName}`;
}

// best
function getFullName({ firstName, lastName }) {
  return `${firstName} ${lastName}`;
}

const arr = [1, 2, 3, 4];

// bad
const first = arr[0];
const second = arr[1];

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

字符串

  1. 字符串不换行

不易读并其不利于搜索

  1. 使用字符串模板

更可读, 更少的冗余代码

// bad
function sayHi(name) {
  return 'How are you, ' + name + '?';
}

// bad
function sayHi(name) {
  return ['How are you, ', name, '?'].join();
}

// bad
function sayHi(name) {
  return `How are you, ${ name }?`;
}

// good
function sayHi(name) {
  return `How are you, ${name}?`;
}
  1. 避免使用不必要的转义字符

使代码更不易理解

// bad
const foo = '\'this\' \i\s \"quoted\"';

// good
const foo = '\'this\' is "quoted"';
const foo = `my name is '${name}'`;
  1. 使用命名函数表达式代替函数声明, 并且声明函数时指定函数名称

函数声明被提升, 这意味着在函数定义之前使用函数变得很容易, 会损害代码的可读性和可维护性, 指定函数名称可以方便debug

// bad
function foo() {
  // ...
}
// bad
const foo = function () {
  // ...
};
// good
// 与变量引用的调用区分开的函数名称
const short = function longUniqueMoreDescriptiveLexicalFoo() {
  // ...
};
  1. 使用括号包含立即执行函数

括号表示该立即执行函数是一个独立的单元

// bad
function () {
  console.log('Welcome to the Internet. Please follow me.');
}();
// good
(function () {
  console.log('Welcome to the Internet. Please follow me.');
}());
  1. 注意函数声明会被提升
// bad
if (currentUser) {
  function test() {
    console.log('Nope.');
  }
}

// good
let test;
if (currentUser) {
  test = () => {
    console.log('Yup.');
  };
}
  1. 函数的形参中不要声明arguments, 可使用 ... 操作符
// bad
function foo(name, options, arguments) {
  // ...
}

// good
function foo(name, options, args) {
  // ...
}

// good
function foo (name, age, ...options){
  // ...
}

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

// good
function concatenateAll(...args) {
  return args.join('');
}
  1. 尽量使用默认参数
// really bad
function handleThings(opts) {
  // 不应该直接改变 函数参数
  // 如果 opts 为逻辑假, 那么它将被赋值为一个空对象
  // be what you want but it can introduce subtle bugs.
  opts = opts || {};
  // ...
}

// still bad
function handleThings(opts) {
  if (opts === void 0) {
    opts = {};
  }
  // ...
}

// good
function handleThings(opts = {}) {
  // ...
}
  1. 在使用默认参数时注意其副作用

可能导致相同的调用不同的结果

var b = 1;
// bad
function count(a = b++) {
  console.log(a);
}
count();  // 1
count();  // 2
count(3); // 3
count();  // 3
  1. 避免使用Function构造函数(new Function)

跟 eval 一样, 可能引起严重漏洞

  1. 优先使用箭头函数

更简洁, 且箭头函数没有烦人的this问题

// bad
[1, 2, 3].map(function (x) {
  const y = x + 1;
  return x * y;
});

// good
[1, 2, 3].map((x) => {
  const y = x + 1;
  return x * y;
});

类和构造函数

  1. 使用 class 关键字创建一个类

更简单, 更可读

  1. 使用extends 来继承类

这是一种内建的不破坏 instanceof的方法

  1. 类方法可以return this 来方便连式调用
// bad
Jedi.prototype.jump = function () {
  this.jumping = true;
  return true;
};

Jedi.prototype.setHeight = function (height) {
  this.height = height;
};

const luke = new Jedi();
luke.jump(); // => true
luke.setHeight(20); // => undefined

// good
class Jedi {
  jump() {
    this.jumping = true;
    return this;
  }

  setHeight(height) {
    this.height = height;
    return this;
  }
}

const luke = new Jedi();

luke.jump()
  .setHeight(20);
  1. 定义类的toString方法, 方便某些场景下使用(alert)
class Jedi {
  constructor(options = {}) {
    this.name = options.name || 'no name';
  }

  getName() {
    return this.name;
  }

  toString() {
    return `Jedi - ${this.getName()}`;
  }
}

const qwang = new Jedi({name: 'qwang'})
alert(qwang) // 'Jedi - qwang'
  1. 在没有显示声明 constructor 时, class 默认会有一个constructor 方法.
// bad
class Jedi {
  constructor() {}

  getName() {
    return this.name;
  }
}

// bad
class Rey extends Jedi {
  constructor(...args) {
    super(...args);
  }
}

// good
class Rey extends Jedi {
  constructor(...args) {
    super(...args);
    this.name = 'Rey';
  }
}

迭代

  1. 尽可能使用js内建的高阶函数来代替 for ...infor ...of

贯彻不可变原则, 代码处理函数返回值比副作用更可推导

const numbers = [1, 2, 3, 4, 5];

// bad
let sum = 0;
for (let num of numbers) {
  sum += num;
}
sum === 15;

// good
let sum = 0;
numbers.forEach((num) => {
  sum += num;
});
sum === 15;

// best (use the functional force)
const sum = numbers.reduce((total, num) => total + num, 0);
sum === 15;

// bad
const increasedByOne = [];
for (let i = 0; i < numbers.length; i++) {
  increasedByOne.push(numbers[i] + 1);
}

// good
const increasedByOne = [];
numbers.forEach((num) => {
  increasedByOne.push(num + 1);
});

// best (keeping it functional)
const increasedByOne = numbers.map(num => num + 1);
  • 摘选自eslint

相关文章

  • 写出更优秀的javascript代码

    类型 在使用复合类型时需要注意其引用: 变量声明与赋值 使用let, const 代替 var: let 和 co...

  • Fly Jquery ( you might not need

    jQuery 作为一款优秀的JavaScript框架,使用 JQuery能够让你写出更加简洁易懂的代码,提高开发效...

  • Javascript代码规范

    目的:总结记录Javascript代码书写规范,写出优美的Javascript代码,代码洁癖只是一种态度。 一、命...

  • 写出整洁的 JavaScript 代码

    前言 每个人写代码风格不一样,但本文给出了十个不同正反例说明,大家可以多参考,但不一定要遵守。本文由@aliveb...

  • 写出漂亮的 JavaScript 代码

    函数 如果参数超过两个,建议使用 ES6 的解构语法,不用考虑参数的顺序。 尽量不要写全局方法 类 使用 ES6 ...

  • 8个要点教你轻松写出优秀Javascript代码

    今天我们来讲讲写好JS代码的几个要点 松耦合 当修改一个组件而不需要更改其他组件时,就做到了松耦合 1、将JS从C...

  • 这几年的生活状态

    记得前几年,自己的目标是写出优秀的代码,写出漂亮的文章;现在有些转变,目标变成做出成功的产品,写出优秀的短篇小说。...

  • jQuery

    jQuery是什么? jQuery是一个快速、简洁的JavaScript框架,一个优秀的JavaScript代码库...

  • 9个JavaScript小技巧:写出更简洁,高效代码

    JavaScript一直在变化进步着,这儿列举了一些小技巧帮你在2019年写出更简洁,高效的可拓展的代码。下面共列...

  • Clean Code之JavaScript代码示例

    译者按: 简洁的代码可以避免写出过多的BUG。 原文: JavaScript Clean Code - Best ...

网友评论

      本文标题:写出更优秀的javascript代码

      本文链接:https://www.haomeiwen.com/subject/vdvkhqtx.html