javascript的原则

写在开头

最近在看原则一本书,发现生活中和工作中很多都是有规律有原则的,代码的世界里也一样,代码其实是写给人看的,机器是看不懂的,它只会按照人类设定的规则去运行。所以把代码写的规范一些,让更多的人看得懂,看得轻松,这就是一件很了不起的事情了,所以我搜集多方资料,为JavaScript也打造了一份属于它的原则,喜欢写JavaScript的朋友或者平时工作中用的多的朋友也可以看一下,相互学习。

Variables (变量)

简单四个字,见名思意。
Bad:

const yyyymmdstr = moment().format('YYYY/MM/DD');

Good:

const currentDate = moment().format('YYYY/MM/DD');

使用有意思的常量

Bad:

setTimeout(blastOff, 86400000);

Good:

const MILLISECONDS_IN_A_DAY = 86400000;

setTimeout(blastOff, MILLISECONDS_IN_A_DAY);

Use explanatory variables

参数要用简洁
Bad:

const address = 'One Infinite Loop, Cupertino 95014';
const cityZipCodeRegex = /[,\]+[,\\s]+(.+?)\s*(\d{5})?$/;
saveCityZipCode(address.match(cityZipCodeRegex)[1], address.match(cityZipCodeRegex)[2]);

Good:

const address = 'One Infinite Loop, Cupertino 95014';
const cityZipCodeRegex = /[,\]+[,\\s]+(.+?)\s*(\d{5})?$/;
const [, city, zipCode] = address.match(cityZipCodeRegex) || [];
saveCityZipCode(city, zipCode);

Avoid Mental Mapping

避免使用看不懂的词汇
Bad:

const locations = ['Austin', 'New York', 'San Francisco'];
locations.forEach((l) => {
doStuff();
doSomeOtherStuff();
// ...
// ...
// ...
// Wait, what is l for again?
dispatch(l);
});

Good:

const locations = ['Austin', 'New York', 'San Francisco'];
locations.forEach((location) => {
doStuff();
doSomeOtherStuff();
// ...
// ...
// ...
dispatch(location);
});

Don't add unneeded context

如果对象名能够说明一些事,那么在值中就不要重复了。

Bad:

const Car = {
carMake: 'Honda',
carModel: 'Accord',
carColor: 'Blue'
};

function paintCar(car) {
car.carColor = 'Red';
}

Good:

const Car = {
make: 'Honda',
model: 'Accord',
color: 'Blue'
};

function paintCar(car) {
car.color = 'Red';
}

Use default arguments instead of short circuiting or conditionals

参数传递时,默认的参数传递最后如下。
Bad:

function createMicrobrewery(name) {
const breweryName = name || 'Hipster Brew Co.';
// ...
}

Good:

function createMicrobrewery(name = 'Hipster Brew Co.') {
// ...
}

Functions should do one thing

一个函数一次只专心做一件事
Bad:

function emailClients(clients) {
clients.forEach((client) => {
const clientRecord = database.lookup(client);
if (clientRecord.isActive()) {
email(client);
}
});
}

Good:

function emailActiveClients(clients) {
clients
.filter(isActiveClient)
.forEach(email);
}

function isActiveClient(client) {
const clientRecord = database.lookup(client);
return clientRecord.isActive();
}

Functions should only be one level of abstraction

复杂的方法应该抽离出独立的函数
Bad:

function parseBetterJSAlternative(code) {
const REGEXES = [
// ...
];

const statements = code.split(' ');
const tokens = [];
REGEXES.forEach((REGEX) => {
statements.forEach((statement) => {
// ...
});
});

const ast = [];
tokens.forEach((token) => {
// lex...
});

ast.forEach((node) => {
// parse...
});
}

Good:

function parseBetterJSAlternative(code) {

const tokens = tokenize(code);
const ast = lexer(tokens);
ast.forEach((node) => {
// parse...
});
}

function tokenize(code) {
const REGEXES = [
// ...
];

const statements = code.split(' ');
const tokens = [];
REGEXES.forEach((REGEX) => {
statements.forEach((statement) => {
tokens.push( /* ... */ );
});
});

return tokens;
}

function lexer(tokens) {
const ast = [];
tokens.forEach((token) => {
ast.push( /* ... */ );
});

return ast;
}

Remove duplicate code

去掉那些重复的代码,能够用一个函数解决的问题,不要拆分成两个

Bad:

function showDeveloperList(developers) {
developers.forEach((developer) => {
const expectedSalary = developer.calculateExpectedSalary();
const experience = developer.getExperience();
const githubLink = developer.getGithubLink();
const data = {
expectedSalary,
experience,
githubLink
};

render(data);

});
}

function showManagerList(managers) {
managers.forEach((manager) => {
const expectedSalary = manager.calculateExpectedSalary();
const experience = manager.getExperience();
const portfolio = manager.getMBAProjects();
const data = {
expectedSalary,
experience,
portfolio
};

render(data);

});
}

Good:

function showEmployeeList(employees) {
employees.forEach((employee) => {
const expectedSalary = employee.calculateExpectedSalary();
const experience = employee.getExperience();

const data = {
  expectedSalary,
  experience
};

switch (employee.type) {
  case 'manager':
    data.portfolio = employee.getMBAProjects();
    break;
  case 'developer':
    data.githubLink = employee.getGithubLink();
    break;
}

render(data);

});
}

Set default objects with Object.assign

尽量使用 Object.assign
Bad:

const menuConfig = {
title: null,
body: 'Bar',
buttonText: null,

cancellable: true
};

function createMenu(config) {
config.title = config.title || 'Foo';
config.body = config.body || 'Bar';
config.buttonText = config.buttonText || 'Baz';
config.cancellable = config.cancellable !== undefined ? config.cancellable : true;
}

createMenu(menuConfig);

Good:

const menuConfig = {
title: 'Order',
// User did not include 'body' key
buttonText: 'Send',
cancellable: true
};

function createMenu(config) {
config = Object.assign({
title: 'Foo',
body: 'Bar',
buttonText: 'Baz',
cancellable: true
}, config);

// config now equals: {title: "Order", body: "Bar", buttonText: "Send", cancellable: true}
// ...
}

createMenu(menuConfig);

Don't use flags as function parameters

别用参数来分离的函数
Bad:

function createFile(name, temp) {
if (temp) {
fs.create(./temp/${name});
} else {
fs.create(name);
}
}

Good:

function createFile(name) {
fs.create(name);
}

function createTempFile(name) {
createFile(./temp/${name});
}

Avoid Side Effects

避免写出副作用的函数
Bad:

let name = 'Ryan McDermott';

function splitIntoFirstAndLastName() {
name = name.split(' ');
}

splitIntoFirstAndLastName();

console.log(name); // ['Ryan', 'McDermott'];

Good:

function splitIntoFirstAndLastName(name) {
return name.split(' ');
}

const name = 'Ryan McDermott';
const newName = splitIntoFirstAndLastName(name);

console.log(name); // 'Ryan McDermott';
console.log(newName); // ['Ryan', 'McDermott'];

Don't write to global functions

不要随意些全局的方法,最后是用calss来扩展
Bad:

Array.prototype.diff = function diff(comparisonArray) {
const hash = new Set(comparisonArray);
return this.filter(elem => !hash.has(elem));
};

Good:

class SuperArray extends Array {
diff(comparisonArray) {
const hash = new Set(comparisonArray);
return this.filter(elem => !hash.has(elem));
}
}

Favor functional programming over imperative programming

用函数式编程,少用命令式编程

Bad:

const programmerOutput = [
{
name: 'Uncle Bobby',
linesOfCode: 500
}, {
name: 'Suzie Q',
linesOfCode: 1500
}, {
name: 'Jimmy Gosling',
linesOfCode: 150
}, {
name: 'Gracie Hopper',
linesOfCode: 1000
}
];

let totalOutput = 0;

for (let i = 0; i < programmerOutput.length; i++) {
totalOutput += programmerOutput[i].linesOfCode;
}

Good:

const programmerOutput = [
{

name: 'Uncle Bobby',
linesOfCode: 500

}, {
name: 'Suzie Q',
linesOfCode: 1500
}, {
name: 'Jimmy Gosling',
linesOfCode: 150
}, {
name: 'Gracie Hopper',
linesOfCode: 1000
}
];

const totalOutput = programmerOutput
.map(output => output.linesOfCode)
.reduce((totalLines, lines) => totalLines + lines);

Encapsulate conditionals

该封装的时候旧的封装

Bad:

if (fsm.state === 'fetching' && isEmpty(listNode)) {
// ...
}

Good:

function shouldShowSpinner(fsm, listNode) {
return fsm.state === 'fetching' && isEmpty(listNode);
}

if (shouldShowSpinner(fsmInstance, listNodeInstance)) {
// ...
}

Avoid negative conditionals

尽量使用肯定的条件

Bad:

function isDOMNodeNotPresent(node) {
// ...
}

if (!isDOMNodeNotPresent(node)) {
// ...
}

Good:

function isDOMNodePresent(node) {
// ...
}

if (isDOMNodePresent(node)) {
// ...
}

Avoid conditionals

一个函数只做一件事,哪怕很艰难,当你觉得麻烦的时候,那就是你再写复杂代码的时候

Bad:

class Airplane {
// ...
getCruisingAltitude() {
switch (this.type) {
case '777':
return this.getMaxAltitude() - this.getPassengerCount();
case 'Air Force One':
return this.getMaxAltitude();
case 'Cessna':
return this.getMaxAltitude() - this.getFuelExpenditure();
}
}
}

Good:

class Airplane {
// ...
}

class Boeing777 extends Airplane {
// ...
getCruisingAltitude() {
return this.getMaxAltitude() - this.getPassengerCount();
}
}

class AirForceOne extends Airplane {
// ...
getCruisingAltitude() {
return this.getMaxAltitude();
}
}

class Cessna extends Airplane {
// ...
getCruisingAltitude() {
return this.getMaxAltitude() - this.getFuelExpenditure();
}
}

Don't over-optimize

现代浏览器其实做了很多优化,只是你未曾知道

Bad:

// On old browsers, each iteration with uncached list.length would be costly
// because of list.length recomputation. In modern browsers, this is optimized.
for (let i = 0, len = list.length; i < len; i++) {
// ...
}

Good:

for (let i = 0; i < list.length; i++) {
// ...
}

Remove dead code

删掉哪些没有用到注释的代码把

Bad:
function oldRequestModule(url) {
// ...
}

function newRequestModule(url) {
// ...
}

const req = newRequestModule;
inventoryTracker('apples', req, 'www.inventory-awesome.io');

Good:

function newRequestModule(url) {
// ...
}

const req = newRequestModule;
inventoryTracker('apples', req, 'www.inventory-awesome.io');

小结

以上主要是基础js代码编写中所需要注意的一些细节,看似都非常简蕴藏着能量非常巨大,平时的细节把握的好,工作中才不会产生很低级的错误。上面离打造干净整洁的代码还有很大一步。知识点得慢慢消化加以实践,我们还是小步慢慢来。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,928评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,192评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,468评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,186评论 1 286
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,295评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,374评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,403评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,186评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,610评论 1 306
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,906评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,075评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,755评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,393评论 3 320
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,079评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,313评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,934评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,963评论 2 351

推荐阅读更多精彩内容

  • 前言 前几天在GitHub看到一篇写PHP简洁之道的译文,觉得还不错,所以转在了自己的博客中,只不过有一些地方好像...
    guanguans阅读 596评论 3 6
  • 用更合理的方式写 JavaScript 目录 声明变量 对象 数组 字符串 函数 箭头函数 模块 迭代器和生成器 ...
    小红依阅读 1,795评论 0 5
  • Ba la la la ~ 读者朋友们,你们好啊,又到了冷锋时间,话不多说,发车! 一、变量 使用有准确...
    王饱饱阅读 267评论 0 3
  • (a fork of Airbnb's Javascript Style Guide) Strikingly ES...
    飘零_zyw阅读 1,156评论 1 2
  • 朋友来上海玩。知道我在学花道,特地送了本川濑敏郎的《一日一花》。这两天有时间好好看了一下,非常喜欢。酷暑天气,没有...
    花间星事阅读 1,153评论 3 13