Heim >Web-Frontend >js-Tutorial >Einführung in Codierungsstandards in Javascript (Codebeispiele)

Einführung in Codierungsstandards in Javascript (Codebeispiele)

不言
不言nach vorne
2019-02-27 10:46:212424Durchsuche

Dieser Artikel bietet Ihnen eine Einführung in die Codierungsstandards in Javascript (Codebeispiele). Ich hoffe, er wird Ihnen als Referenz dienen.

Namenskonvention

  • Standardvariablen werden in Kamel-Schreibweise benannt

  • 'ID' ist in der Variablenname Alle Großbuchstaben für Konstanten

  • Konstruktoren werden mit Unterstrichen verbunden und der erste Buchstabe wird groß geschrieben

  • jquery-Objekte müssen mit „$“ beginnen ' Benennung

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');

Lokale Variablenbenennungskonvention

  • s: stellt eine Zeichenfolge dar. Zum Beispiel: sName, sHtml;

  • n: steht für eine Zahl. Zum Beispiel: nPage, nTotal;

  • b: steht für Logik. Zum Beispiel: bChecked, bHasLogin;

  • a: stellt ein Array dar. Zum Beispiel: aList, aGroup;

  • r: stellt einen regulären Ausdruck dar. Zum Beispiel: rDomain, rEmail;

  • f: stellt eine Funktion dar. Zum Beispiel: fGetHtml, fInit;

  • o: Stellt andere Objekte dar, die oben nicht erwähnt wurden, wie zum Beispiel: oButton, oDate; Die Funktionsbenennung lautet

unter Verwendung der allgemeinen Verbkonvention:

kann bestimmen, ob eine Aktion ausgeführt werden kann, und die Funktion gibt einen booleschen Wert zurück. true: ausführbar; false: nicht ausführbar
  • hat bestimmt, ob es einen bestimmten Wert enthält, und die Funktion gibt einen booleschen Wert zurück. true: enthält diesen Wert; false: enthält diesen Wert nicht

  • bestimmt, ob es sich um einen bestimmten Wert handelt, und die Funktion gibt einen booleschen Wert zurück. true: für einen bestimmten Wert; false: nicht für einen bestimmten Wert

  • get ruft einen bestimmten Wert ab, die Funktion gibt einen nicht-booleschen Wert zurück

  • set legt einen bestimmten Wert fest, keinen Rückgabewert, gibt zurück, ob die Einstellung erfolgreich ist, oder gibt einen verketteten Objektladevorgang zurück, lädt einige Daten, keinen Rückgabewert oder gibt das Ergebnis zurück, ob der Ladevorgang abgeschlossen ist

// 是否可阅读
function canRead() {
 return true;
}
// 获取名称
function getName() {
 return this.name;
}
  • Referenzen

  • Verwenden Sie const für alle Referenzen, verwenden Sie nicht var.

    eslint:prefer-const, no-const-assign

    Dadurch wird sichergestellt, dass Sie die Referenz nicht neu zuweisen können, was zu Fehlern und schwer verständlichem Code führen kann.

    // bad
    var a = 1;
    var b = 2;
    // good
    const a = 1;
    const b = 2;
    Wenn Sie unbedingt veränderbare Referenzen benötigen, verwenden Sie let anstelle von var .

    eslint: no-var jscs: disallowVar
    // bad
    var count = 1;
    if (true) {
    count += 1;
    }
    // good, 使用 let.
    let count = 1;
    if (true) {
    count += 1;
    }
    Objekte

    Erstellen Sie Objekte mit wörtlicher Syntax.

    eslint: no-new-object

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

    Verwenden Sie berechnete Eigenschaftsnamen, wenn Sie Objekte mit dynamischen Eigenschaftsnamen erstellen.

    Sie ermöglichen es Ihnen, alle Eigenschaften eines Objekts an einem Ort zu definieren.

    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,
    };
    Verwenden Sie die Kurzsyntax der Objektmethode.

    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;
      },
    };
    Verwenden Sie die Objekteigenschaften-Kurzschriftsyntax.

    eslint: object-shorthand jscs: requireEnhancedObjectLiterals

    const lukeSkywalker = 'Luke Skywalker';
    // bad
    const obj = {
      lukeSkywalker: lukeSkywalker,
    };
    // good
    const obj = {
      lukeSkywalker,
    };
    Kurzschrifteigenschaften am Anfang der Objektdeklaration gruppieren

    Erleichtert das Erkennen, welche Eigenschaften Kurzschriftsyntax verwenden

    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,
    };
    Zitieren Sie nur Attribute ungültiger Bezeichner.

    eslint: quote-props jscs: disallowQuotedKeysInObjects
    Im Allgemeinen denken wir, dass es einfacher zu lesen ist. Es verbessert die Syntaxhervorhebung und lässt sich von vielen JS-Engines einfacher optimieren.

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

    Verwenden Sie den Objektverbreitungsoperator, um Objekte flach zu kopieren und dabei Vorrang vor Object.assign zu haben. Verwenden Sie den Objektrestoperator, um ein neues Objekt zu erhalten, bei dem bestimmte Eigenschaften weggelassen wurden.

    // 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 }
    Arrays Arrays
    Erstellen Sie Arrays mit Literalen.

    eslint: no-array-constructor

    // bad
    const items = new Array();
    // good
    const items = [];

    Verwenden Sie den Array-Spread-Operator..., um das Array zu kopieren.

    // bad
    const len = items.length;
    const itemsCopy = [];
    let i;
    for (i = 0; i < len; i += 1) {
    itemsCopy[i] = items[i];
    }
    // good
    const itemsCopy = [...items];

    Verwenden Sie den Spread-Operator … anstelle von Array.from, um ein Array-ähnliches Objekt in ein Array umzuwandeln.

    const foo = document.querySelectorAll(&#39;.foo&#39;);
    // good
    const nodes = Array.from(foo);
    // best
    const nodes = [...foo];

    Verwenden Sie Array.from anstelle des Spread-Operators ..., um Iterationen abzubilden, da dadurch die Erstellung eines Zwischenarrays vermieden wird.

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

    Destrukturierung Destrukturierung

    Verwenden Sie die Objektdestrukturierung, wenn Sie auf mehrere Eigenschaften eines Objekts zugreifen und diese verwenden.

    eslint: Prefer-destructuring jscs: requireObjectDestructuring

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

    Array-Destrukturierung verwenden.

    eslint:prefer-destructuring jscs: requireArrayDestructuring

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

    Verwenden Sie die Objektdestrukturierung für mehrere Rückgabewerte anstelle der Array-Destrukturierung. jscs: disallowArrayDestructuringReturn

    Sie können neue Eigenschaften hinzufügen oder die Reihenfolge im Laufe der Zeit ändern, ohne die Position beim Aufruf zu ändern.

    // 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);

    Strings Strings

    Strings verwenden einfache Anführungszeichen ''.
    eslint: quotes jscs: validateQuoteMarks

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

    Verwenden Sie beim programmgesteuerten Erstellen von Zeichenfolgen Vorlagenzeichenfolgen anstelle der Zeichenfolgenverkettung.

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

    / bad
    function sayHi(name) {
      return &#39;How are you, &#39; + name + &#39;?&#39;;
    }
    // bad
    function sayHi(name) {
      return [&#39;How are you, &#39;, name, &#39;?&#39;].join();
    }
    // bad
    function sayHi(name) {
      return `How are you, ${ name }?`;
    }
    // good
    function sayHi(name) {
       return `How are you, name?`;
    }

    Verwenden Sie eval() niemals für Strings, es öffnet zu viele Schwachstellen.

    eslint: no-eval

    Funktionen Funktionen

    Verwenden Sie benannte Funktionsausdrücke anstelle von Funktionsdeklarationen.

    eslint: func-style 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(&#39;Welcome to the Internet. Please follow me.&#39;);
    }());

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

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

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

    // 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, &#39;key&#39;) ? 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 < array.length; i++) { 
      let value = array[i]; 
      sum += value;
       if (value) {
          truthyCount++; 
        } 
     }
    // good 
    const array = [1, 2, 3]; 
    let num = 1; num += 1; num -= 1; 
    const sum = array.reduce((a, b) => 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 || c > 0 || d + 1 === 0;
    // bad
    const bar = a ** b - 5 % d;
    // bad
    if (a || b && c) {
    return d;
    }
    // good
    const foo = (a && b < 0) || c > 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;
    }
    )


    Das obige ist der detaillierte Inhalt vonEinführung in Codierungsstandards in Javascript (Codebeispiele). Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

    Stellungnahme:
    Dieser Artikel ist reproduziert unter:segmentfault.com. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen