찾다
웹 프론트엔드JS 튜토리얼Javascript의 코딩 표준 소개(코드 예제)

Javascript의 코딩 표준 소개(코드 예제)

Feb 27, 2019 am 10:46 AM
javascript표준화하다

이 글은 Javascript의 코딩 표준(코드 예제)을 소개합니다. 도움이 필요한 친구들이 참고할 수 있기를 바랍니다.

이름 지정 규칙

  • 표준 변수의 이름은 카멜 표기법으로 지정됩니다.

  • 'ID'는 변수 이름에서 모두 대문자로 표시됩니다.

  • 상수는 모두 대문자로 표시됩니다. 생성자를 연결하려면 밑줄을 사용하고, 첫 글자를 대문자로 표시하세요.

  • jquery 객체의 이름은 '$'

let thisIsMyName;
let goodID;
let reportURL;
let AndroidVersion;
let iOSVersion;
let MAX_COUNT = 10;
function Person(name) {
this.name = name;
}
// not good
let body = $('body');
// good
let $body = $('body');

로컬 변수 명명 규칙

  • s: 문자열을 나타냅니다. 예: sName, sHtml

  • n: 숫자를 나타냅니다. 예: nPage, nTotal

  • b: 논리를 나타냅니다. 예: bChecked, bHasLogin

  • a: 배열을 나타냅니다. 예: aList, aGroup

  • r: 정규식을 나타냅니다. 예: rDomain, rEmail

  • f: 기능을 나타냅니다. 예: fGetHtml, fInit;

  • o: oButton, oDate와 같이 위에서 언급되지 않은 다른 개체를 나타냅니다.

  • 는 작업을 수행할 수 있는지 여부를 결정하고 함수는 부울 값을 반환합니다. true: 실행 가능, false: 실행 불가능

은 특정 값이 포함되어 있는지 확인하고 함수는 부울 값을 반환합니다. true: 이 값을 포함하고 false: 이 값을 포함하지 않습니다.

    이 값이 특정 값인지 확인하고 함수는 부울 값을 반환합니다. true: 특정 값에 대해; false: 특정 값에 대해 아님
  • get 특정 값을 가져오면 함수는 부울이 아닌 값을 반환합니다.
  • set 특정 값을 설정하고 반환 값은 없으며 설정 여부를 반환합니다. 성공하거나 반환됩니다. 연결된 객체 로드는 특정 데이터를 로드하고, 값을 반환하지 않거나 로드 완료 여부에 대한 결과를 반환합니다.
  • eslint: Prefer-const, no-const-sign

  • 이렇게 하면 참조를 재할당할 수 없게 되어 버그나 이해하기 어려운 코드가 발생할 수 있습니다.
  • // 是否可阅读
    function canRead() {
     return true;
    }
    // 获取名称
    function getName() {
     return this.name;
    }

    변경 가능한 참조가 꼭 필요한 경우 var 대신 let을 사용하세요.

  • eslint: no-var jscs: disallowVar
  • // bad
    var a = 1;
    var b = 2;
    // good
    const a = 1;
    const b = 2;

    Objects

  • 리터럴 구문을 사용하여 개체를 만듭니다.

eslint: no-new-object

// bad
var count = 1;
if (true) {
count += 1;
}
// good, 使用 let.
let count = 1;
if (true) {
count += 1;
}
동적 속성 이름이 있는 객체를 생성할 때 계산된 속성 이름을 사용하세요.

한 곳에서 개체의 모든 속성을 정의할 수 있습니다.

// bad
const item = new Object();
// good
const item = {};

객체 메서드 단축 구문을 사용하세요.

eslint: object-shorthand jscs: requireEnhancedObjectLiterals
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,
};

객체 속성 단축 구문을 사용하세요.

eslint: object-shorthand jscs: requireEnhancedObjectLiterals

// 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,
};

유효하지 않은 식별자에 대해서는 속성만 인용하세요.

eslint: quote-props jscs: disallowQuotedKeysInObjects

일반적으로 말하면 읽기가 더 쉽다고 생각합니다. 구문 강조가 향상되고 많은 JS 엔진에서 최적화하기가 더 쉽습니다.

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,
};

객체 확산 연산자를 사용하면 객체를 얕게 복사할 수 있으며 객체 할당보다 우선 적용됩니다. 특정 속성이 생략된 새 객체를 얻으려면 객체 나머지 연산자를 사용하십시오.

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

Arrays

리터럴을 사용하여 배열을 만듭니다.

eslint: no-array-constructor

// very bad
const original = { a: 1, b: 2 };
const copy = Object.assign(original, { c: 3 }); //  `original` 是可变的 ಠ_ಠ
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 }

배열 확산 연산자를 사용하여 배열을 복사합니다.

// bad
const items = new Array();
// good
const items = [];
Array.from 대신 확산 연산자를 사용하여 배열과 유사한 객체를 배열로 변환하세요.
// bad
const len = items.length;
const itemsCopy = [];
let i;
for (i = 0; i <h3 id="중간-배열-생성을-방지하기-위해-스프레드-연산자-대신-Array-from을-사용하여-반복을-매핑합니다">중간 배열 생성을 방지하기 위해 스프레드 연산자 대신 Array.from을 사용하여 반복을 매핑합니다. </h3><pre class="brush:php;toolbar:false">const foo = document.querySelectorAll('.foo');
// good
const nodes = Array.from(foo);
// best
const nodes = [...foo];

Destructuring

객체의 여러 속성에 액세스하고 사용할 때 객체 구조 분해를 사용하세요.

eslint: 선호 파괴 jscs: requireObjectDestructuring

// bad
const baz = [...foo].map(bar);
// good
const baz = Array.from(foo, bar);

배열 파괴를 사용하세요.

eslint: Prefer-Destructuring jscs: requireArrayDestructuring

// 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`;
}

여러 반환 값에 대해 배열 분해 대신 객체 분해를 사용하세요. jscs: disallowArrayDestructuringReturn

호출 시 위치를 변경하지 않고 시간이 지남에 따라 새 속성을 추가하거나 순서를 변경할 수 있습니다.

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

문자열 문자열

문자열은 작은따옴표 ''를 사용합니다.

eslint: quote jscs: verifyQuoteMarks

// bad
function processInput(input) {
  return [left, right, top, bottom];
}
// 调用者需要考虑返回数据的顺序
const [left, __, top] = processInput(input);
// good
function processInput(input) {
  return { left, right, top, bottom };
}
// 调用者只选择他们需要的数据
const { left, top } = processInput(input);

프로그래밍 방식으로 문자열을 작성할 때 문자열 연결 대신 템플릿 문자열을 사용하세요.

eslint: Prefer-template template-curly-spacing jscs: requireTemplateStrings

// bad
const name = "Capt. Janeway";
// bad - 模板字面量应该包含插值或换行符
const name = `Capt. Janeway`;
// good
const name = 'Capt. Janeway';

문자열에 eval()을 사용하지 마세요. 취약점이 너무 많습니다.

eslint: no-eval

Functions

함수 선언 대신 명명된 함수 표현식을 사용하세요.

eslint: func 스타일 jscs: disallowFunctionDeclarations

函数声明很容易被提升(Hoisting),这对可读性和可维护性来说都是不利的;
/ bad
function foo() {
  // ...
}
// bad
const foo = function () {
  // ...
};
// good 
// 用明显区别于变量引用调用的词汇命名
const short = function longUniqueMoreDescriptiveLexicalFoo() {
  // ...
};

用圆括号包裹立即调用函数表达式 (IIFE)。

eslint: wrap-iife jscs: requireParenthesesAroundIIFE

一个立即调用函数表达式是一个单独的单元 – 将函数表达式包裹在括号中,后面再跟一个调用括号,这看上去很紧凑。
// 立即调用函数表达式 (IIFE)
(function () {
console.log('Welcome to the Internet. Please follow me.');
}());

不要使用 arguments。可以选择 rest 语法 … 替代。

使用 … 能明确你要传入的参数。另外 rest(剩余)参数是一个真正的数组,而 arguments 是一个类数组(Array-like)。
// bad
function concatenateAll() {
  const args = Array.prototype.slice.call(arguments);
  return args.join('');
}
// good
function concatenateAll(...args) {
  return args.join('');
}

使用默认参数语法,而不要使用一个变化的函数参数

// really bad
function handleThings(opts) {
  // 更加糟糕: 如果参数 opts 是 falsy(假值) 的话,它将被设置为一个对象,
  // 这可能是你想要的,但它可以引起一些小的错误。
  opts = opts || {};
  // ...
}
// still bad
function handleThings(opts) {
  if (opts === void 0) {
  opts = {};
}
// ...
}
// good
function handleThings(opts = {}) {
  // ...
}

始终将默认参数放在最后。

// bad
function handleThings(opts = {}, name) {
// ...
}
// good
function handleThings(name, opts = {}) {
// ...
}

隔开函数签名,括号两边用空格隔开。

// bad
const f = function(){};
const g = function (){};
const h = function() {};
// good
const x = function () {};
const y = function a() {};

不要改变参数。

eslint: no-param-reassign

操作作为参数传入的对象,可能会在调用原始对象时造成不必要的变量副作用。(对象是引用类型)
// bad
function f1(obj) {
obj.key = 1;
}
// good
function f2(obj) {
  const key = Object.prototype.hasOwnProperty.call(obj, 'key') ? obj.key : 1;
}

箭头函数 Arrow Functions

当您必须使用匿名函数(如在传递一个内联回调时),请使用箭头函数表示法。

eslint: prefer-arrow-callback, arrow-spacing jscs: requireArrowFunctions

它创建了一个在 this 上下文中执行的函数的版本,这通常是你想要的,而且这样的写法更为简洁。
// bad
[1, 2, 3].map(function (x) {
  const y = x + 1;
  return x * y;
});
// bad
[1, 2, 3].map( _ => {
  
  return 0;
});
// good
[1, 2, 3].map((x) => {
  const y = x + 1;
  return x * y;
});
// good
[1, 2, 3].map(() => {
  
  return 0;
});

如果函数体由一个返回无副作用(side effect)的expression(表达式)的单行语句组成,那么可以省略大括号并使用隐式返回。否则,保留大括号并使用 return 语句。

// bad
[1, 2, 3].map(number => {
const nextNumber = number + 1;
return `A string containing the nextNumber.`;
});
// good
[1, 2, 3].map(number => `A string containing the number.`);

如果表达式跨多行,将其包裹在括号中,可以提高可读性。

// bad
['get', 'post', 'put'].map(httpMethod => Object.prototype.hasOwnProperty.call(
  httpMagicObjectWithAVeryLongName,
  httpMethod,
  )
);
// good
['get', 'post', 'put'].map(httpMethod => (
  Object.prototype.hasOwnProperty.call(
  httpMagicObjectWithAVeryLongName,
  httpMethod,
  )
));

如果你的函数只有一个参数并且不使用大括号,则可以省略参数括号。否则,为了清晰和一致性,总是给参数加上括号。

// bad
[1, 2, 3].map((x) => x * x);
// good
[1, 2, 3].map(x => x * x);
// good
[1, 2, 3].map(number => (
`A long string with the number. It’s so long that we don’t want it to take up space on the .map line!`
));
// 总是添加()
// bad
[1, 2, 3].map(x => {
  const y = x + 1;
  return x * y;
});
// good
[1, 2, 3].map((x) => {
  const y = x + 1;
  return x * y;
});

避免使用比较运算符(=)时,混淆箭头函数语法(=>)。

// bad
const itemHeight = item => item.height > 256 ? item.largeSize : item.smallSize;
// bad
const itemHeight = (item) => item.height > 256 ? item.largeSize : item.smallSize;
// good
const itemHeight = item => (item.height > 256 ? item.largeSize : item.smallSize);
// good
const itemHeight = (item) => {
  const { height, largeSize, smallSize } = item;
  return height > 256 ? largeSize : smallSize;
};

类 Classes & 构造函数 Constructors

总是使用 *class。避免直接操作 prototype 。

// 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 继承。

因为 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];
  }
}

如果没有指定,类有一个默认的构造函数。一个空的构造函数或者只是委托给父类则不是必须的。

eslint: no-useless-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';
  }
}

避免重复类成员。

eslint: no-dupe-class-members

// bad
class Foo {
  bar() { return 1; }
  bar() { return 2; }
}
// good
class Foo {
  bar() { return 1; }
}
// good
class Foo {
  bar() { return 2; }
}

模块 Modules

总是使用模块 (import/export) 而不是其他非标准模块系统。

// bad
const AirbnbStyleGuide = require('./AirbnbStyleGuide');
module.exports = AirbnbStyleGuide.es6;
// ok
import AirbnbStyleGuide from './AirbnbStyleGuide';
export default AirbnbStyleGuide.es6;
// best
import { es6 } from './AirbnbStyleGuide';
export default es6;

不要使用通配符 import(导入)。

这样能确保你只有一个默认 export(导出)。
// bad
import * as AirbnbStyleGuide from './AirbnbStyleGuide';
// good
import AirbnbStyleGuide from './AirbnbStyleGuide';

不要从 import(导入) 中直接 export(导出)。

虽然一行代码简洁明了,但有一个明确的 import(导入) 方法和一个明确的 export(导出) 方法,使事情能保持一致。
// bad
// filename es6.js
export { es6 as default } from './AirbnbStyleGuide';
// good
// filename es6.js
import { es6 } from './AirbnbStyleGuide';
export default es6;

一个地方只在一个路径中 import(导入) 。

// bad
import foo from 'foo';
// … 其他一些 imports … //
import { named1, named2 } from 'foo';
// good
import foo, { named1, named2 } from 'foo';
// good
import foo, {
  named1,
  named2,
} from 'foo';

不要 export(导出) 可变绑定。

eslint: import/no-mutable-exports

一般应该避免可变性,特别是在导出可变绑定时。虽然一些特殊情况下,可能需要这种技术,但是一般而言,只应该导出常量引用。
// bad
let foo = 3;
export { foo };
// good
const foo = 3;
export { foo };

在只有单个导出的模块中,默认 export(导出) 优于命名 export(导出)。

eslint: import/prefer-default-export

为了鼓励更多的文件只有一个 export(导出),这有利于模块的可读性和可维护性。
// bad
export function foo() {}
// good
export default function foo() {}

将所有 import 导入放在非导入语句的上面。

eslint: import/first

由于 import 被提升,保持他们在顶部,防止意外的行为。
// bad
import foo from 'foo';
foo.init();
import bar from 'bar';
// good
import foo from 'foo';
import bar from 'bar';
foo.init();

多行导入应该像多行数组和对象字面量一样进行缩进。

// bad
import {longNameA, longNameB, longNameC, longNameD, longNameE} from 'path';
// good
import {
longNameA,
longNameB,
longNameC,
longNameD,
longNameE,
} from 'path';

属性 Properties

使用 点语法(.) 来访问对象的属性。

eslint: dot-notation jscs: requireDotNotation

const luke = {
jedi: true,
age: 28,
};
// bad
const isJedi = luke['jedi'];
// good
const isJedi = luke.jedi;

当通过变量访问属性时使用中括号 []。

const luke = {
jedi: true,
age: 28,
};
function getProp(prop) {
return luke[prop];
}
const isJedi = getProp('jedi');

求幂时使用求幂运算符 ** 。

eslint: no-restricted-properties.

// bad
const binary = Math.pow(2, 10);
// good
const binary = 2 ** 10;

变量 Variables

总是使用 const 或 let 来声明变量。 不这样做会导致产生全局变量。 我们希望避免污染全局命名空间。

eslint: no-undef prefer-const

// bad
superPower = new SuperPower();
// good
const superPower = new SuperPower();

将所有的 const 和 let 分组 。

当你需要把已分配的变量分配给一个变量时非常有用
// bad
let i, len, dragonball,
items = getItems(),
goSportsTeam = true;
// bad
let i;
const items = getItems();
let dragonball;
const goSportsTeam = true;
let len;
// good
const goSportsTeam = true;
const items = getItems();
let dragonball;
let i;
let length;

变量不要链式赋值。

eslint: no-multi-assign

链接变量赋值会创建隐式全局变量。
// bad
(function example() {
// JavaScript 将其解析为
// let a = ( b = ( c = 1 ) );
// let关键字只适用于变量a;
// 变量b和c变成了全局变量。
let a = b = c = 1;
}());
console.log(a); // 抛出 ReferenceError(引用错误)
console.log(b); // 1
console.log(c); // 1
// good
(function example() {
let a = 1;
let b = a;
let c = a;
}());
console.log(a); // 抛出 ReferenceError(引用错误)
console.log(b); // 抛出 ReferenceError(引用错误)
console.log(c); // 抛出 ReferenceError(引用错误)
// 同样适用于 `const`

避免使用一元递增和递减运算符(++, –)。

根据 eslint 文档,一元递增和递减语句会受到自动插入分号的影响,并可能导致应用程序中的值递增或递减,从而导致无提示错误。使用像 num += 1 而不是 num++ 或 num ++ 这样的语句来改变你的值也更具有表现力。不允许一元递增和递减语句也会阻止您无意中预先递增/递减值,这也会导致程序中的意外行为。
// bad
const array = [1, 2, 3];
let num = 1;
num++;
--num;
let sum = 0;
let truthyCount = 0;
for (let i = 0; i  a + b, 0);
const truthyCount = array.filter(Boolean).length;

比较运算符 Comparison Operators 和 等号 Equality

使用 === 和 !== 优先于 == 和 !=。

eslint: eqeqeq

对于布尔值使用简写,但对于字符串和数字使用显式比较。

// bad
if (isValid === true) {
// ...
}
// good
if (isValid) {
// ...
}
// bad
if (name) {
// ...
}
// good
if (name !== '') {
// ...
}
// bad
if (collection.length) {
// ...
}
// good
if (collection.length > 0) {
// ...
}

在 case 和 default 子句中,使用大括号来创建包含词法声明的语句块(例如 let, const, function, 和 class).

eslint: no-case-declarations

// bad
switch (foo) {
  case 1:
    let x = 1;
  break;
  case 2:
    const y = 2;
  break;
  case 3:
    function f() {
      // ...
    }
  break;
default:
  class C {}
}
// good
switch (foo) {
  case 1: {
    let x = 1;
    break;
  }
  case 2: {
    const y = 2;
    break;
  }
  case 3: {
    function f() {
      // ...
    }
    break;
  }
  case 4:
    bar();
    break;
  default: {
    class C {}
  }
}

三元表达式不应该嵌套,通常写成单行表达式。

eslint: no-nested-ternary

// bad
const foo = maybe1 > maybe2
? "bar"
: value1 > value2 ? "baz" : null;
// 拆分成2个分离的三元表达式
const maybeNull = value1 > value2 ? 'baz' : null;
// better
const foo = maybe1 > maybe2
? 'bar'
: maybeNull;
// best
const foo = maybe1 > maybe2 ? 'bar' : maybeNull;

避免不必要的三元表达式语句。

eslint: no-unneeded-ternary

/ bad
const foo = a ? a : b;
const bar = c ? true : false;
const baz = c ? false : true;
// good
const foo = a || b;
const bar = !!c;
const baz = !c;

当运算符混合在一个语句中时,请将其放在括号内。混合算术运算符时,不要将 * 和 % 与 + , -,,/ 混合在一起。

eslint: no-mixed-operators

这可以提高可读性,并清晰展现开发者的意图。
/ bad
const foo = a && b  0 || d + 1 === 0;
// bad
const bar = a ** b - 5 % d;
// bad
if (a || b && c) {
return d;
}
// good
const foo = (a && b  0 || (d + 1 === 0);
// good
const bar = (a ** b) - (5 % d);
// good
if ((a || b) && c) {
return d;
}
// good
const bar = a + b / c * d;

代码块 Blocks

使用大括号包裹所有的多行代码块。

eslint: nonblock-statement-body-position

// bad
if (test)
  return false;
// good
if (test) return false;
// good
if (test) {
  return false;
}
// bad
function foo() { return false; }
// good
function bar() {
  return false;
}

如果通过 if 和 else 使用多行代码块,把 else 放在 if 代码块闭合括号的同一行。

eslint: brace-style

// bad
if (test) {
  thing1();
  thing2();
}
else {
  thing3();
}
// good
if (test) {
  thing1();
  thing2();
} else {
  thing3();
}

如果一个 if 块总是执行一个 return 语句,后面的 else 块是不必要的。在 else if 块中的 return,可以分成多个 if 块来 return 。

eslint: no-else-return

// bad
function foo() {
  if (x) {
    return x;
  } else {
    return y;
  }
}
// bad
function cats() {
  if (x) {
    return x;
  } else if (y) {
    return y;
  }
}
// bad
function dogs() {
  if (x) {
    return x;
  } else {
  if (y) {
    return y;
  }
}
}
// good
function foo() {
  if (x) {
    return x;
  }
return y;
}
// good
function cats() {
  if (x) {
    return x;
  }
  if (y) {
    return y;
  }
}
//good
function dogs(x) {
  if (x) {
    if (z) {
      return y;
  }
} else {
  return z;
  }
}

控制语句 Control Statements

如果您的控制语句(if, while 的)太长或超过最大行长度,那么每个(分组)条件可以放单独一行。逻辑运算符应该放在每行起始处。

// bad
if ((foo === 123 || bar === 'abc') && doesItLookGoodWhenItBecomesThatLong() && isThisReallyHappening()) {
 thing1();
}
// bad
if (foo === 123 &&
  bar === 'abc') {
  thing1();
}
// bad
if (foo === 123
  && bar === 'abc') {
  thing1();
}
// bad
if (
  foo === 123 &&
  bar === 'abc'
) {
  thing1();
}
// good
if (
  foo === 123
  && bar === 'abc'
) {
  thing1();
}
// good
if (
  (foo === 123 || bar === "abc")
  && doesItLookGoodWhenItBecomesThatLong()
  && isThisReallyHappening()
) {
  thing1();
}
// good
if (foo === 123 && bar === 'abc') {
  thing1();
}

注释 Comments

多行注释使用 /* … /。

/**
* @param {Grid} grid 需要合并的Grid
* @param {Array} cols 需要合并列的Index(序号)数组;从0开始计数,序号也包含。
* @param {Boolean} isAllSome 是否2个tr的cols必须完成一样才能进行合并。true:完成一样;false(默认):不完全一样
* @return void
* @author 单志永 2018/11/8
*/
function mergeCells(grid, cols, isAllSome) {
    // Do Something
}

单行注释使用 // 。将单行注释放在续注释的语句上方。在注释之前放置一个空行,除非它位于代码块的第一行。

// bad
const active = true;  // is current tab
// good
// is current tab
const active = true;
// bad
function getType() {
  console.log('fetching type...');
  // set the default type to 'no type'
  const type = this.type || 'no type';
  return type;
}
// good
function getType() {
  console.log('fetching type...');
  // set the default type to 'no type'
  const type = this.type || 'no type';
  return type;
}
// also good
function getType() {
  // set the default type to 'no type'
  const type = this.type || 'no type';
  return type;
}

所有注释符和注释内容用一个空格隔开,让它更容易阅读。

eslint: spaced-comment

// bad
//is current tab
const active = true;
// good
// is current tab
const active = true;
// bad
/**
*make() returns a new element
*based on the passed-in tag name
*/
function make(tag) {
// ...
return element;
}
// good
/**
* make() returns a new element
* based on the passed-in tag name
*/
function make(tag) {
// ...
return element;
}

给注释增加 FIXME 或 TODO 的前缀,可以帮助其他开发者快速了解这个是否是一个需要重新复查的问题,或是你正在为需要解决的问题提出解决方案。这将有别于常规注释,因为它们是可操作的。使用 FIXME – need to figure this out 或者 TODO – need to implement。

使用 // FIXME: 来标识需要修正的问题。注:如果代码中有该标识,说明标识处代码需要修正,甚至代码是错误的,不能工作,需要修复,如何修正会在说明中简略说明。

lass Calculator extends Abacus {
  constructor() {
    super();
    // FIXME: shouldn’t use a global here
    total = 0;
  }
}

使用 // TODO: 来标识需要实现的问题。注:如果代码中有该标识,说明在标识处有功能代码待编写,待实现的功能在说明中会简略说明。

class Calculator extends Abacus {
  constructor() {
    super();
    // TODO: total should be configurable by an options param
    this.total = 0;
  }
}

空格 Whitespace

使用 2 个空格作为缩进

// bad
function foo() {
∙∙∙∙let name;
}
// bad
function bar() {
∙let name;
}
// good
function baz() {
∙∙let name;
}

在大括号前放置 1 个空格。

eslint: space-before-blocks jscs: requireSpaceBeforeBlockStatements

// bad
function test(){
  console.log('test');
}
// good
function test() {
  console.log('test');
}
// bad
dog.set('attr',{
  age: '1 year',
  breed: 'Bernese Mountain Dog',
});
// good
dog.set('attr', {
  age: '1 year',
  breed: 'Bernese Mountain Dog',
});

在控制语句(if、while 等)的小括号前放一个空格。在函数调用及声明中,不在函数的参数列表前加空格。

eslint: keyword-spacing jscs: requireSpaceAfterKeywords

// bad
if(isJedi) {
  fight ();
}
// good
if (isJedi) {
  fight();
}
// bad
function fight () {
  console.log ('Swooosh!');
}
// good
function fight() {
  console.log('Swooosh!');
}

使用空格把运算符隔开。

eslint: space-infix-ops jscs: requireSpaceBeforeBinaryOperators, requireSpaceAfterBinaryOperators

// bad
const x=y+5;
// good
const x = y + 5;

在文件末尾插入一个空行。

eslint: eol-last

// bad
import { es6 } from './AirbnbStyleGuide';
// ...
export default es6;

// bad
import { es6 } from './AirbnbStyleGuide';
// ...
export default es6;

// good
import { es6 } from './AirbnbStyleGuide';
// ...
export default es6;

长方法链式调用时使用缩进(2个以上的方法链式调用)。使用一个点 . 开头,强调该行是一个方法调用,不是一个新的声明。

eslint: newline-per-chained-call no-whitespace-before-property

// bad
$('#items').find('.selected').highlight().end().find('.open').updateCount();

// bad
$('#items').
find('.selected').
highlight().
end().
find('.open').
updateCount();

// good
$('#items')
.find('.selected')
.highlight()
.end()
.find('.open')
.updateCount();

// bad
const leds = stage.selectAll('.led').data(data).enter().append('svg:svg').classed('led', true)
.attr('width', (radius + margin) * 2).append('svg:g')
.attr('transform', `translate(${radius + margin},${radius + margin})`)
.call(tron.led);
// good
const leds = stage.selectAll('.led')
.data(data)
.enter().append('svg:svg')
.classed('led', true)
.attr('width', (radius + margin) * 2)
.append('svg:g')
.attr('transform', `translate(${radius + margin},${radius + margin})`)
.call(tron.led);

// good
const leds = stage.selectAll('.led').data(data);

不要在圆括号内加空格。

// bad
function bar( foo ) {
  return foo;
}
// good
function bar(foo) {
  return foo;
}
// bad
if ( foo ) {
  console.log(foo);
}
// good
if (foo) {
  console.log(foo);
}

不要在中括号内添加空格。

eslint: array-bracket-spacing jscs: disallowSpacesInsideArrayBrackets

// bad
const foo = [ 1, 2, 3 ];
console.log(foo[ 0 ]);
// good
const foo = [1, 2, 3];
console.log(foo[0]);

在大括号内添加空格

// bad
const foo = {clark: 'kent'};
// good
const foo = { clark: 'kent' };

类型转换 Type Casting & Coercion

在声明语句的开始处就执行强制类型转换.

字符串:

eslint: no-new-wrappers

// => this.reviewScore = 9;
// bad
const totalScore = new String(this.reviewScore); // typeof totalScore 是 "object" 而不是 "string"
// bad
const totalScore = this.reviewScore + ''; // 调用 this.reviewScore.valueOf()
// bad
const totalScore = this.reviewScore.toString(); // 不能保证返回一个字符串
// good
const totalScore = String(this.reviewScore);

使数字: 使用 Number 进行转换,而 parseInt 则始终以基数解析字串。

eslint: radix no-new-wrappers

const inputValue = '4';
// bad
const val = new Number(inputValue);
// bad
const val = +inputValue;
// bad
const val = inputValue >> 0;
// bad
const val = parseInt(inputValue);
// good
const val = Number(inputValue);
// good
const val = parseInt(inputValue, 10);

布尔值:

eslint: no-new-wrappers

const age = 0;
// bad
const hasAge = new Boolean(age);
// good
const hasAge = Boolean(age);
// best
const hasAge = !!age;

命名规则 Naming Conventions

避免使用单字母名称。使你的命名具有描述性。

eslint: id-length

// bad
function q() {
// ...
}
// good
function query() {
// ...
}

当命名对象,函数和实例时使用驼峰式命名。

eslint: camelcase jscs: requireCamelCaseOrUpperCaseIdentifiers

// bad
const OBJEcttsssss = {};
const this_is_my_object = {};
function c() {}
// good
const thisIsMyObject = {};
function thisIsMyFunction() {}

当命名构造函数或类的时候使用 PascalCase 式命名,(注:即单词首字母大写)。

eslint: new-cap

// bad
function user(options) {
  this.name = options.name;
}
const bad = new user({
  name: 'nope',
});
// good
class User {
  constructor(options) {
    this.name = options.name;
  }
}
const good = new User({
  name: 'yup',
});

当 导出(export) 一个默认函数时使用驼峰式命名。你的文件名应该和你的函数的名字一致。

function makeStyleGuide() {
// ...
}
export default makeStyleGuide;

当导出一个 构造函数 / 类 / 单例 / 函数库 / 纯对象时使用 PascalCase 式命名,(愚人码头注:即单词首字母大写)。

const AirbnbStyleGuide = {
  es6: {
    },
};
export default AirbnbStyleGuide;

存取器 Accessors

属性的存取器函数不是必须的。

別使用 JavaScript 的 getters/setters,因为它们会导致意想不到的副作用,而且很难测试,维护和理解。相反,如果要使用存取器函数,使用 getVal() 及 setVal(‘hello’)。

// bad
class Dragon {
  get age() {
    // ...
  }
  set age(value) {
    // ...
  }
}
// good
class Dragon {
  getAge() {
    // ...
  }
  setAge(value) {
    // ...
  }
}

如果属性/方法是一个 boolean, 使用 isVal() 或 hasVal() 方法。

// bad
if (!dragon.age()) {
  return false;
}
// good
if (!dragon.hasAge()) {
  return false;
}
)


위 내용은 Javascript의 코딩 표준 소개(코드 예제)의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명
이 기사는 segmentfault에서 복제됩니다. 침해가 있는 경우 admin@php.cn으로 문의하시기 바랍니다. 삭제
JavaScript : 웹 언어의 다양성 탐색JavaScript : 웹 언어의 다양성 탐색Apr 11, 2025 am 12:01 AM

JavaScript는 현대 웹 개발의 핵심 언어이며 다양성과 유연성에 널리 사용됩니다. 1) 프론트 엔드 개발 : DOM 운영 및 최신 프레임 워크 (예 : React, Vue.js, Angular)를 통해 동적 웹 페이지 및 단일 페이지 응용 프로그램을 구축합니다. 2) 서버 측 개발 : Node.js는 비 차단 I/O 모델을 사용하여 높은 동시성 및 실시간 응용 프로그램을 처리합니다. 3) 모바일 및 데스크탑 애플리케이션 개발 : 크로스 플랫폼 개발은 개발 효율을 향상시키기 위해 반응 및 전자를 통해 실현됩니다.

JavaScript의 진화 : 현재 동향과 미래 전망JavaScript의 진화 : 현재 동향과 미래 전망Apr 10, 2025 am 09:33 AM

JavaScript의 최신 트렌드에는 Typescript의 Rise, 현대 프레임 워크 및 라이브러리의 인기 및 WebAssembly의 적용이 포함됩니다. 향후 전망은보다 강력한 유형 시스템, 서버 측 JavaScript 개발, 인공 지능 및 기계 학습의 확장, IoT 및 Edge 컴퓨팅의 잠재력을 포함합니다.

Demystifying JavaScript : 그것이하는 일과 중요한 이유Demystifying JavaScript : 그것이하는 일과 중요한 이유Apr 09, 2025 am 12:07 AM

JavaScript는 현대 웹 개발의 초석이며 주요 기능에는 이벤트 중심 프로그래밍, 동적 컨텐츠 생성 및 비동기 프로그래밍이 포함됩니다. 1) 이벤트 중심 프로그래밍을 사용하면 사용자 작업에 따라 웹 페이지가 동적으로 변경 될 수 있습니다. 2) 동적 컨텐츠 생성을 사용하면 조건에 따라 페이지 컨텐츠를 조정할 수 있습니다. 3) 비동기 프로그래밍은 사용자 인터페이스가 차단되지 않도록합니다. JavaScript는 웹 상호 작용, 단일 페이지 응용 프로그램 및 서버 측 개발에 널리 사용되며 사용자 경험 및 크로스 플랫폼 개발의 유연성을 크게 향상시킵니다.

Python 또는 JavaScript가 더 좋습니까?Python 또는 JavaScript가 더 좋습니까?Apr 06, 2025 am 12:14 AM

Python은 데이터 과학 및 기계 학습에 더 적합한 반면 JavaScript는 프론트 엔드 및 풀 스택 개발에 더 적합합니다. 1. Python은 간결한 구문 및 풍부한 라이브러리 생태계로 유명하며 데이터 분석 및 웹 개발에 적합합니다. 2. JavaScript는 프론트 엔드 개발의 핵심입니다. Node.js는 서버 측 프로그래밍을 지원하며 풀 스택 개발에 적합합니다.

JavaScript를 어떻게 설치합니까?JavaScript를 어떻게 설치합니까?Apr 05, 2025 am 12:16 AM

JavaScript는 이미 최신 브라우저에 내장되어 있기 때문에 설치가 필요하지 않습니다. 시작하려면 텍스트 편집기와 브라우저 만 있으면됩니다. 1) 브라우저 환경에서 태그를 통해 HTML 파일을 포함하여 실행하십시오. 2) Node.js 환경에서 Node.js를 다운로드하고 설치 한 후 명령 줄을 통해 JavaScript 파일을 실행하십시오.

Quartz에서 작업이 시작되기 전에 알림을 보내는 방법은 무엇입니까?Quartz에서 작업이 시작되기 전에 알림을 보내는 방법은 무엇입니까?Apr 04, 2025 pm 09:24 PM

쿼츠 타이머를 사용하여 작업을 예약 할 때 미리 쿼츠에서 작업 알림을 보내는 방법 작업의 실행 시간은 CRON 표현식에 의해 설정됩니다. 지금...

JavaScript에서 생성자의 프로토 타입 체인에서 함수의 매개 변수를 얻는 방법은 무엇입니까?JavaScript에서 생성자의 프로토 타입 체인에서 함수의 매개 변수를 얻는 방법은 무엇입니까?Apr 04, 2025 pm 09:21 PM

JavaScript 프로그래밍에서 JavaScript의 프로토 타입 체인에서 함수 매개 변수를 얻는 방법 프로토 타입 체인의 기능 매개 변수를 이해하고 조작하는 방법은 일반적이고 중요한 작업입니다 ...

Wechat Mini 프로그램 웹 뷰에서 Vue.js 동적 스타일 변위가 실패한 이유는 무엇입니까?Wechat Mini 프로그램 웹 뷰에서 Vue.js 동적 스타일 변위가 실패한 이유는 무엇입니까?Apr 04, 2025 pm 09:18 PM

WeChat 애플릿 웹 뷰에서 vue.js를 사용하는 동적 스타일 변위 실패가 vue.js를 사용하는 이유를 분석합니다.

See all articles

핫 AI 도구

Undresser.AI Undress

Undresser.AI Undress

사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover

AI Clothes Remover

사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool

Undress AI Tool

무료로 이미지를 벗다

Clothoff.io

Clothoff.io

AI 옷 제거제

AI Hentai Generator

AI Hentai Generator

AI Hentai를 무료로 생성하십시오.

인기 기사

R.E.P.O. 에너지 결정과 그들이하는 일 (노란색 크리스탈)
3 몇 주 전By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. 최고의 그래픽 설정
3 몇 주 전By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. 아무도들을 수없는 경우 오디오를 수정하는 방법
3 몇 주 전By尊渡假赌尊渡假赌尊渡假赌
WWE 2K25 : Myrise에서 모든 것을 잠금 해제하는 방법
3 몇 주 전By尊渡假赌尊渡假赌尊渡假赌

뜨거운 도구

Atom Editor Mac 버전 다운로드

Atom Editor Mac 버전 다운로드

가장 인기 있는 오픈 소스 편집기

ZendStudio 13.5.1 맥

ZendStudio 13.5.1 맥

강력한 PHP 통합 개발 환경

Dreamweaver Mac版

Dreamweaver Mac版

시각적 웹 개발 도구

SecList

SecList

SecLists는 최고의 보안 테스터의 동반자입니다. 보안 평가 시 자주 사용되는 다양한 유형의 목록을 한 곳에 모아 놓은 것입니다. SecLists는 보안 테스터에게 필요할 수 있는 모든 목록을 편리하게 제공하여 보안 테스트를 더욱 효율적이고 생산적으로 만드는 데 도움이 됩니다. 목록 유형에는 사용자 이름, 비밀번호, URL, 퍼징 페이로드, 민감한 데이터 패턴, 웹 셸 등이 포함됩니다. 테스터는 이 저장소를 새로운 테스트 시스템으로 간단히 가져올 수 있으며 필요한 모든 유형의 목록에 액세스할 수 있습니다.

WebStorm Mac 버전

WebStorm Mac 버전

유용한 JavaScript 개발 도구