JS編碼規(guī)范

一汞舱、javascript代碼規(guī)范

  1. 變量

    1.1 一直使用 const 來聲明變量唐瀑,如果不這樣做就會產(chǎn)生全局變量。我們需要避免全局命名空間的污染噪沙。地球隊長已經(jīng)警告過我們了炼彪。(譯注:全局,global 亦有全球的意思正歼。地球隊長的責任是保衛(wèi)地球環(huán)境辐马,所以他警告我們不要造成「全球」污染。)

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

    1.2 使用 const局义、let 聲明變量喜爷,而不使用 var冗疮。

  1. 數(shù)組

    2.1 使用字面值創(chuàng)建數(shù)組。

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

    2.2 向數(shù)組添加元素時使用 Arrary#push 替代直接賦值檩帐。

    const someStack = [];
    
    // bad
    someStack[someStack.length] = 'abracadabra';
    
    // good
    someStack.push('abracadabra');
    

    2.3 使用拓展運算符 ... 復制數(shù)組术幔。

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

    2.4 使用 Array#from 把一個類數(shù)組對象轉換成數(shù)組。

    const foo = document.querySelectorAll('.foo');
    const nodes = Array.from(foo);
    
  2. 字符串

    3.1 字符串使用單引號 ''
    3.2 字符串過長時轿塔,使用+連接字符串
    過度使用字串連接符號可能會對性能造成影響特愿。

    // bad
    const errorMessage = 'This is a super long error that was thrown because of Batman. When you stop to think about how Batman had anything to do with this, you would get nowhere fast.';
    
    // bad
    const errorMessage = 'This is a super long error that was thrown because \
    of Batman. When you stop to think about how Batman had anything to do \
    with this, you would get nowhere \
    fast.';
    
    // good
    const errorMessage = 'This is a super long error that was thrown because ' +
      'of Batman. When you stop to think about how Batman had anything to do ' +
      'with this, you would get nowhere fast.';
    

    3.3 程序化生成字符串時,使用模板字符串代替字符串連接勾缭。

    // bad
    function sayHi(name) {
       return 'How are you, ' + name + '?';
    }
    
    // bad
    function sayHi(name) {
      return ['How are you, ', name, '?'].join();
    }
    
    // good
    function sayHi(name) {
      return `How are you, ${name}?`;
    }
    
  3. 函數(shù)

    4.1 永遠不要把參數(shù)命名為 arguments。這將取代原來函數(shù)作用域內的 arguments 對象目养。

    // bad
    function nope(name, options, arguments) {
      // ...stuff...
    }
    
    // good
    function yup(name, options, args) {
      // ...stuff...
    }
    

    4.2 不要使用 arguments俩由。可以選擇 rest 語法 ... 替代癌蚁。

    為什么幻梯?使用 ... 能明確你要傳入的參數(shù)。另外 rest 參數(shù)是一個真正的數(shù)組努释,而 arguments 是一個類數(shù)組碘梢。

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

    4.3 直接給函數(shù)的參數(shù)指定默認值,不要使用一個變化的函數(shù)參數(shù)伐蒂。

    // really bad
    function handleThings(opts) {
      // 不煞躬!我們不應該改變函數(shù)參數(shù)。
      // 更加糟糕: 如果參數(shù) opts 是 false 的話逸邦,它就會被設定為一個對象恩沛。
      // 但這樣的寫法會造成一些 Bugs。
      //(譯注:例如當 opts 被賦值為空字符串缕减,opts 仍然會被下一行代碼設定為一個空對象雷客。)
      opts = opts || {};
      // ...
    }
    
    // still bad
    function handleThings(opts) {
      if (opts === void 0) {
        opts = {};
      }
      // ...
    }
    
    // good
    function handleThings(opts = {}) {
      // ...
    }
    

    4.4 除非參數(shù)過多,不然不要傳入一個對象

    // bad
    function handleThings(user) {
      // ...
      return user.username == ''
    }
    
    // good
    function handleThings(username) {
      // ...
      return username == ''
    }
    
  4. 箭頭函數(shù)

    5.1 當你必須使用函數(shù)表達式(或傳遞一個匿名函數(shù))時桥狡,使用箭頭函數(shù)符號搅裙。

    為什么?因為箭頭函數(shù)創(chuàng)造了新的一個 this 執(zhí)行環(huán)境,通常情況下都能滿足你的需求裹芝,而且這樣的寫法更為簡潔部逮。

    為什么不?如果你有一個相當復雜的函數(shù)局雄,你或許可以把邏輯部分轉移到一個函數(shù)聲明上甥啄。

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

    5.2 如果一個函數(shù)適合用一行寫出并且只有一個參數(shù),那就把花括號炬搭、圓括號和 return 都省略掉蜈漓。如果不是穆桂,那就不要省略。

    為什么融虽?語法糖享完。在鏈式調用中可讀性很高。

    為什么不有额?當你打算回傳一個對象的時候般又。

    // good
    [1, 2, 3].map(x => x * x);
    // good
    [1, 2, 3].reduce((total, n) => {
     return total + n;
    }, 0);
    
  5. 屬性

    6.1 使用 . 來訪問對象的屬性。

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

    6.2 當通過變量訪問屬性時使用中括號 []巍佑。

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

    7.1 使用解構存取和使用多屬性對象茴迁。
    為什么?因為解構能減少臨時引用屬性萤衰。

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

    7.2 對數(shù)組使用解構賦值堕义。

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

    7.3 需要回傳多個值時,使用對象解構脆栋,而不是數(shù)組解構倦卖。

    為什么?增加屬性或者改變排序不會改變調用時的位置椿争。

    // bad
    function processInput(input) {
        // then a miracle occurs
        return [left, right, top, bottom];
    }
    // 調用時需要考慮回調數(shù)據(jù)的順序怕膛。
    const [left, __, top] = processInput(input);
    // good
    function processInput(input) {
     // then a miracle occurs
     return { left, right, top, bottom };
    }
    // 調用時只選擇需要的數(shù)據(jù)
    const { left, right } = processInput(input);
    
  7. 比較運算符 & 等號

    8.1

    優(yōu)先使用

    === 和 !==
    

    而不是

    == 和 !=
    

    8.2 條件表達式例如 if 語句通過抽象方法 ToBoolean 強制計算它們的表達式并且總是遵守下面的規(guī)則:

    • 對象 被計算為 true
    • Undefined 被計算為 false
    • Null 被計算為 false
    • Boolean 被計算為truefalse
    • 數(shù)字 如果是 +0-0秦踪、或 NaN被計算為 false, 否則為 true
    • 字符串 如果是空字符串 '' 被計算為 false褐捻,否則為 true
    if ([0]) {
      // true
      // An array is an object, objects evaluate to true
    }
    
  8. 注釋

    9.1 使用 /** ... */ 作為多行注釋。包含描述洋侨、指定所有參數(shù)和返回值的類型和值舍扰。

    // bad
    // make() returns a new element
    // based on the passed in tag name
    //
    // @param {String} tag
    // @return {Element} element
    function make(tag) {
    
      // ...stuff...
    
      return element;
    }
    
    // good
    /**
     * make() returns a new element
     * based on the passed in tag name
     *
     * @param {String} tag
     * @return {Element} element
     */
    function make(tag) {
    
      // ...stuff...
    
      return element;
    }
    

    9.2 使用 // 作為單行注釋。在評論對象上面另起一行使用單行注釋希坚。在注釋前插入空行边苹。

    9.3 // 符號后添加一個空格

    9.4 方法使用jsdoc的方式注釋

  1. 分號

    10.1 匿名方法后必須使用分號

    代碼壓縮后如果多個匿名方法壓縮在一起會變成代碼錯誤。

  2. 命名規(guī)制

    11.1 避免單字母命名裁僧。命名應具備描述性个束。

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

    11.2 使用駝峰式命名對象、函數(shù)和實例聊疲。

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

    11.3 使用帕斯卡式命名構造函數(shù)或類茬底。

    // 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',
    });
    
  3. 原型鏈

    12.1 盡量避免覆蓋原型鏈的方式修改javascript基礎對象,如String获洲、Date

  4. 模塊

    13.1 總是使用模組 (import/export) 而不是其他非標準模塊系統(tǒng)阱表。你可以編譯為你喜歡的模塊系統(tǒng)。

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

二、React/JSX

  1. Declaration 聲明模塊

    使用 class extends React.Component 而不是 React.createClass ,除非你有充足的理由來使用這些方法.

    // bad
      const Listing = React.createClass({
        // ...
        render() {
          return <div>{this.state.hello}</div>;
        }
      });
    
      // good
      class Listing extends React.Component {
        // ...
        render() {
          return <div>{this.state.hello}</div>;
        }
      }
    
  2. Alignment 代碼對齊

    2.1 遵循以下的JSX語法縮進/格式. eslint: react/jsx-closing-bracket-location

    // bad
    <Foo superLongParam="bar"
         anotherSuperLongParam="baz" />
    
    // good, 有多行屬性的話, 新建一行關閉標簽
    <Foo
      superLongParam="bar"
      anotherSuperLongParam="baz"
    />
    
    // 若能在一行中顯示, 直接寫成一行
    <Foo bar="bar" />
    
    // 子元素按照常規(guī)方式縮進
    <Foo
      superLongParam="bar"
      anotherSuperLongParam="baz"
    >
      <Quux />
    </Foo>
    
  3. Quotes 單引號還是雙引號

    3.1 對于JSX屬性值總是使用雙引號("), 其他均使用單引號(').
    為什么? HTML屬性也是用雙引號, 因此JSX的屬性也遵循此約定.

  1. Spacing 空格

    4.1 總是在自動關閉的標簽前加一個空格最爬,正常情況下也不需要換行. eslint: no-multi-spaces, react/jsx-space-before-closing

    // bad
    <Foo/>
    
    // very bad
    <Foo                 />
    
    // bad
    <Foo
     />
    
    // good
    <Foo />
    

    4.2 不要在JSX {} 引用括號里兩邊加空格. eslint: react/jsx-curly-spacing

    // bad
    <Foo bar={ baz } />
    
    // good
    <Foo bar={baz} />
    
  2. Props 屬性

    5.1 JSX屬性名使用駱駝式風格camelCase.

    // bad
    <Foo
      UserName="hello"
      phone_number={12345678}
    />
    
    // good
    <Foo
      userName="hello"
      phoneNumber={12345678}
    />
    

    5.2 對于所有非必須的屬性涉馁,總是手動去定義defaultProps屬性.

    為什么? propTypes 可以作為模塊的文檔說明, 并且聲明 defaultProps 的話意味著閱讀代碼的人不需要去假設一些默認值。更重要的是, 顯示的聲明默認屬性可以讓你的模塊跳過屬性類型的檢查.

    // bad
    function SFC({ foo, bar, children }) {
      return <div>{foo}{bar}{children}</div>;
    }
    SFC.propTypes = {
      foo: PropTypes.number.isRequired,
      bar: PropTypes.string,
      children: PropTypes.node,
    };
    
    // good
    function SFC({ foo, bar }) {
      return <div>{foo}{bar}</div>;
    }
    SFC.propTypes = {
      foo: PropTypes.number.isRequired,
      bar: PropTypes.string,
    };
    SFC.defaultProps = {
      bar: '',
      children: null,
    };
    
    
  3. Parentheses 括號

    6.1 將多行的JSX標簽寫在 ()里. eslint: react/wrap-multilines

    // bad
    render() {
      return <MyComponent className="long body" foo="bar">
               <MyChild />
             </MyComponent>;
    }
    
    // good
    render() {
      return (
        <MyComponent className="long body" foo="bar">
          <MyChild />
        </MyComponent>
      );
    }
    
    // good, 單行可以不需要
    render() {
      const body = <div>hello</div>;
      return <MyComponent>{body}</MyComponent>;
    }
    
  4. Tags 標簽

    7.1 對于沒有子元素的標簽來說總是自己關閉標簽. eslint: react/self-closing-comp

    // bad
    <Foo className="stuff"></Foo>
    
    // good
    <Foo className="stuff" />
    

7.2 如果模塊有多行的屬性爱致, 關閉標簽時新建一行. eslint: react/jsx-closing-bracket-location

// bad
<Foo
  bar="bar"
  baz="baz" />

// good
<Foo
  bar="bar"
  baz="baz"
/>
  1. Methods 函數(shù)

    8.1 當在 render() 里使用事件處理方法時烤送,提前在構造函數(shù)里把 this 綁定上去. eslint: react/jsx-no-bind

    // bad
      class extends React.Component {
        onClickDiv() {
          // do stuff
        }
    
        render() {
          return <div onClick={this.onClickDiv.bind(this)} />
        }
      }
    
      // good
      class extends React.Component {
        constructor(props) {
          super(props);
    
          this.onClickDiv = this.onClickDiv.bind(this);
        }
    
        onClickDiv() {
          // do stuff
        }
    
        render() {
          return <div onClick={this.onClickDiv} />
        }
      }
     
      // good
      class extends React.Component {
        constructor(props) {
          super(props);
        }
    
        onClickDiv = () => {
          // do stuff
        }
    
        render() {
          return <div onClick={this.onClickDiv} />
        }
      }
    

    8.2 在 render 方法中總是確保 return 返回值. eslint: react/require-render-return

    // bad
    render() {
      (<div />);
    }
    
    // good
    render() {
      return (<div />);
    }
    
  2. Ordering React 模塊生命周期

    主要規(guī)范組件內部方法的定義順序。

    Es6 class 定義規(guī)范:

    static 方法
    constructor
    getChildContext
    componentWillMount
    componentDidMount
    componentWillReceiveProps
    shouldComponentUpdate
    componentWillUpdate
    componentDidUpdate
    componentWillUnmount
    clickHandlers + eventHandlers 如 onClickSubmit() 或 onChangeDescription()
    getter methods for render 如 getSelectReason() 或 getFooterContent()
    render methods 如 renderNavigation() 或 renderProfilePicture()
    render
    

    以 Es6 Class 定義的組件為例

    class Person extends React.Component {
        static defaultProps = {}
        static propTypes = {}
        // 構造函數(shù)
        constructor (props) {
            super(props);
            // 定義 state
            this.state = { smiling: false };
        }
        
        // 生命周期方法
        componentWillMount () {}
        componentDidMount () {}
        componentWillUnmount () {}
          
        
        // getters and setters
        get attr() {}
        
        // handlers
        handleClick = () => {}
        
        // render
        renderChild() {}
        render () {}
    }
    
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末糠悯,一起剝皮案震驚了整個濱河市帮坚,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌互艾,老刑警劉巖试和,帶你破解...
    沈念sama閱讀 218,858評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異忘朝,居然都是意外死亡灰署,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,372評論 3 395
  • 文/潘曉璐 我一進店門局嘁,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人晦墙,你說我怎么就攤上這事悦昵。” “怎么了晌畅?”我有些...
    開封第一講書人閱讀 165,282評論 0 356
  • 文/不壞的土叔 我叫張陵但指,是天一觀的道長。 經(jīng)常有香客問我抗楔,道長棋凳,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,842評論 1 295
  • 正文 為了忘掉前任连躏,我火速辦了婚禮剩岳,結果婚禮上,老公的妹妹穿的比我還像新娘入热。我一直安慰自己拍棕,他們只是感情好,可當我...
    茶點故事閱讀 67,857評論 6 392
  • 文/花漫 我一把揭開白布勺良。 她就那樣靜靜地躺著绰播,像睡著了一般。 火紅的嫁衣襯著肌膚如雪尚困。 梳的紋絲不亂的頭發(fā)上蠢箩,一...
    開封第一講書人閱讀 51,679評論 1 305
  • 那天,我揣著相機與錄音,去河邊找鬼谬泌。 笑死滔韵,一個胖子當著我的面吹牛,可吹牛的內容都是我干的呵萨。 我是一名探鬼主播奏属,決...
    沈念sama閱讀 40,406評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼潮峦!你這毒婦竟也來了囱皿?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 39,311評論 0 276
  • 序言:老撾萬榮一對情侶失蹤忱嘹,失蹤者是張志新(化名)和其女友劉穎嘱腥,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體拘悦,經(jīng)...
    沈念sama閱讀 45,767評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡齿兔,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,945評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了础米。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片分苇。...
    茶點故事閱讀 40,090評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖屁桑,靈堂內的尸體忽然破棺而出医寿,到底是詐尸還是另有隱情,我是刑警寧澤蘑斧,帶...
    沈念sama閱讀 35,785評論 5 346
  • 正文 年R本政府宣布靖秩,位于F島的核電站,受9級特大地震影響竖瘾,放射性物質發(fā)生泄漏沟突。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,420評論 3 331
  • 文/蒙蒙 一捕传、第九天 我趴在偏房一處隱蔽的房頂上張望惠拭。 院中可真熱鬧,春花似錦乐横、人聲如沸求橄。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,988評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽罐农。三九已至,卻和暖如春催什,著一層夾襖步出監(jiān)牢的瞬間涵亏,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,101評論 1 271
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留气筋,地道東北人拆内。 一個月前我還...
    沈念sama閱讀 48,298評論 3 372
  • 正文 我出身青樓,卻偏偏與公主長得像宠默,于是被迫代替她去往敵國和親麸恍。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 45,033評論 2 355

推薦閱讀更多精彩內容