前端开发规范

一、目的

  • 文章主要实现的目的:代码一致性和最佳实践
  • 通过代码风格的一致性,降低维护代码的成本以及改善多人协作的效率。
  • 同时遵守最佳实践,确保页面性能得到最佳优化和高效的代码。
  • 本文章只是起指导作用,除个别条目强制之外,大多数为非强制约束,开发者可根据自己的实际情况自行决定是否要遵守,该指南只是保证大方向一致性和最佳实践的阶段性总结,不是最后结论,它会随着时间而变化。

    二、基本规范

    1. 结构、样式、行为分离

    尽量确保文档和模板只包含 HTML 结构,样式都放到样式表里,行为都放到脚本里。

    2. 缩进

    统一两个空格缩进,不要使用 Tab 或者 Tab、空格混搭。

    3. 文件编码

    使用不带 BOM 的 utf-8 编码。

  • 在 HTML中指定编码 <meta charset="utf-8"> ;
  • 无需使用 @charset 指定样式表的编码,它默认为 utf-8 (参考 @charset);
  • 4. 一律使用小写字母

    <!-- 推荐 -->
    <img src="trechina.png" alt="创迹软件">
    
    <!-- 不推荐 -->
    <A HREF="/">主页</A>
    /* 推荐 */
    color: #e5e5e5;
    
    /* 不推荐 */
    color: #E5E5E5;

    5. 省略外链资源 URL 协议部分

    省略外链资源(图片及其它媒体资源)URL 中的 http / https 协议,使 URL 成为相对地址,避免 Mixed Content 问题,减小文件字节数。

    其它协议(ftp 等)的 URL 不省略。

    <!-- 推荐 -->
    <script src="//cdn.bootcss.com/jquery/3.5.0/jquery.min.js"></script>
    
    <!-- 不推荐 -->
    <script src="https://cdn.bootcss.com/jquery/3.5.0/jquery.min.js"></script>
    /* 推荐 */
    .example {
      background: url(//www.google.com/images/example);
    }
    
    /* 不推荐 */
    .example {
      background: url(http://www.google.com/images/example);
    }

    6. 统一注释

    通过配置编辑器,可以提供快捷键来输出一致认可的注释模式。

    HTML 注释
  • 模块注释
    <!-- 文章列表列表模块 -->
    <div class="article-list">
    ...
    </div>
  • 区块注释
    “`html
    <!–
    @name: Drop Down Menu
    @description: Style of top bar drop down menu.
    @author: TRE(tre@gmail.com)
  • ->
  • CSS 注释

    组件块和子组件块以及声明块之间使用一空行分隔,子组件块之间三空行分隔;

    /* ==========================================================================
       组件块
     ============================================================================ */
    
    /* 子组件块
     ============================================================================ */
    .selector {
      padding: 15px;
      margin-bottom: 15px;
    }
    
    
    
    /* 子组件块
     ============================================================================ */
    .selector-secondary {
      display: block; /* 注释*/
    }
    
    .selector-three {
      display: span;
    }
    JavaScript 注释
  • 单行注释
  • 必须独占一行。// 后跟一个空格,缩进与下一行被注释说明的代码一致。

  • 多行注释
  • 避免使用 /*...*/ 这样的多行注释。有多行注释内容时,使用多个单行注释。

  • 函数/方法注释
    1. 函数/方法注释必须包含函数说明,有参数和返回值时必须使用注释标识。;
    2. 参数和返回值注释必须包含类型信息和说明;
    3. 当函数是内部函数,外部不可访问时,可以使用 @inner 标识;
    /**
     * 函数描述
     *
     * @param {string} p1 参数1的说明
     * @param {string} p2 参数2的说明,比较长
     *     那就换行了.
     * @param {number=} p3 参数3的说明(可选)
     * @return {Object} 返回值描述
     */
    function foo(p1, p2, p3) {
        var p3 = p3 || 10;
        return {
            p1: p1,
            p2: p2,
            p3: p3
        };
    }
  • 文件注释
  • 文件注释用于告诉不熟悉这段代码的读者这个文件中包含哪些东西。 应该提供文件的大体内容, 它的作者, 依赖关系和兼容性信息。如下:

    /**
     * @fileoverview Description of file, its uses and information
     * about its dependencies.
     * @author user@trechina.com (Firstname Lastname)
     * Copyright 2020 T.R.E. China Inc. All Rights Reserved.
     */

    三、HTML

    1. 文档类型

    为每个 HTML 页面的第一行添加标准模式(standard mode)的声明, 这样能够确保在每个浏览器中拥有一致的表现。

    <!DOCTYPE html>

    2. 语言属性

    <!-- 中文 -->
    <html lang="zh-Hans">
    
    <!-- 简体中文 -->
    <html lang="zh-cmn-Hans">
    
    <!-- 繁体中文 -->
    <html lang="zh-cmn-Hant">
    
    <!-- English -->
    <html lang="en">

    3. 字符编码

  • 以无 BOM 的 utf-8 编码作为文件格式;
  • 指定字符编码的 meta 必须是 head 的第一个直接子元素;
  • <html>
      <head>
        <meta charset="utf-8">
        ......
      </head>
      <body>
        ......
      </body>
    </html>

    4. IE 兼容模式

    优先使用最新版本的IE 和 Chrome 内核

    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">

    5. SEO 优化

    <head>
      <meta charset="utf-8">
      <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
      <!-- SEO -->
      <title>Style Guide</title>
      <meta name="keywords" content="your keywords">
      <meta name="description" content="your description">
      <meta name="author" content="author,email address">
    </head>

    6. viewport

  • viewport: 一般指的是浏览器窗口内容区的大小,不包含工具条、选项卡等内容;
  • width: 浏览器宽度,输出设备中的页面可见区域宽度;
  • device-width: 设备分辨率宽度,输出设备的屏幕可见宽度;
  • initial-scale: 初始缩放比例;
  • maximum-scale: 最大缩放比例;
  • 为移动端设备优化,设置可见区域的宽度和初始缩放比例。

    <meta name="viewport" content="width=device-width, initial-scale=1.0">

    7. iOS 图标

  • apple-touch-icon 图片自动处理成圆角和高光等效果;
  • apple-touch-icon-precomposed 禁止系统自动添加效果,直接显示设计原图;
  • <!-- iPhone 和 iTouch,默认 57x57 像素,必须有 -->
    <link rel="apple-touch-icon-precomposed" href="/apple-touch-icon-57x57-precomposed.png">
    
    <!-- iPad,72x72 像素,可以没有,但推荐有 -->
    <link rel="apple-touch-icon-precomposed" href="/apple-touch-icon-72x72-precomposed.png" sizes="72x72">
    
    <!-- Retina iPhone 和 Retina iTouch,114x114 像素,可以没有,但推荐有 -->
    <link rel="apple-touch-icon-precomposed" href="/apple-touch-icon-114x114-precomposed.png" sizes="114x114">
    
    <!-- Retina iPad,144x144 像素,可以没有,但推荐有 -->
    <link rel="apple-touch-icon-precomposed" href="/apple-touch-icon-144x144-precomposed.png" sizes="144x144">

    8. favicon

    在未指定 favicon 时,大多数浏览器会请求 Web Server 根目录下的 favicon.ico 。为了保证 favicon 可访问,避免404,必须遵循以下两种方法之一:

  • 在 Web Server 根目录放置 favicon.ico 文件;
  • 使用 link 指定 favicon;
  • <link rel="shortcut icon" href="path/to/favicon.ico">

    9. HEAD 模板

    <!DOCTYPE html>
    <html lang="zh-cmn-Hans">
    <head>
      <meta charset="utf-8">
      <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
      <title>Style Guide</title>
      <meta name="description" content="不超过150个字符">
      <meta name="keywords" content="">
      <meta name="author" content="name, email@gmail.com">
    
      <!-- 为移动设备添加 viewport -->
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
    
      <!-- iOS 图标 -->
      <link rel="apple-touch-icon-precomposed" href="/apple-touch-icon-57x57-precomposed.png">
    
      <link rel="alternate" type="application/rss+xml" title="RSS" href="/rss.xml" />
      <link rel="shortcut icon" href="path/to/favicon.ico">
    </head>

    10. 标签

  • 自闭合(self-closing)标签,无需闭合 ( 例如: img input br hr 等 );
  • 可选的闭合标签(closing tag),需闭合 ( 例如:</li> 或 </body> );
  • 尽量减少标签数量;
  • <img src="images/google.png" alt="Google">
    <input type="text" name="title">
    
    <ul>
      <li>Style</li>
      <li>Guide</li>
    </ul>
    
    <!-- 不推荐 -->
    <span class="avatar">
      <img src="...">
    </span>
    
    <!-- 推荐 -->
    <img class="avatar" src="...">

    11. Class 与 ID

  • class 应以功能或内容命名,不以表现形式命名;
  • class 与 id 单词字母小写,多个单词组成时,采用中划线-分隔;
  • 使用唯一的 id 作为 Javascript hook, 同时避免创建无样式信息的 class;
  • <!-- 不推荐 -->
    <div class="j-hook left contentWrapper"></div>
    
    <!-- 推荐 -->
    <div id="j-hook" class="sidebar content-wrapper"></div>

    12. 属性顺序

    HTML 属性应该按照特定的顺序出现以保证易读性。

  • id
  • class
  • name
  • data-xxx
  • src, for, type, href
  • title, alt
  • aria-xxx, role
  • <a id="..." class="..." data-modal="toggle" href="###"></a>
    
    <input class="form-control" type="text">
    
    <img src="..." alt="...">

    13. 引号

    属性的定义,统一使用双引号。

    <!-- 推荐 -->
    <span id="j-hook" class="text">Google</span>
    
    <!-- 不推荐 -->
    <span id='j-hook' class=text>Google</span>

    14. 嵌套

    a 不允许嵌套 div这种约束属于语义嵌套约束,与之区别的约束还有严格嵌套约束,比如a 不允许嵌套 a

    严格嵌套约束在所有的浏览器下都不被允许;而语义嵌套约束,浏览器大多会容错处理,生成的文档树可能相互不太一样。

    语义嵌套约束

  • <li> 用于 <ul> 或 <ol> 下;
  • <dd><dt> 用于 <dl> 下;
  • <thead><tbody><tfoot><tr><td> 用于 <table> 下;
  • 严格嵌套约束

  • inline-Level 元素,仅可以包含文本或其它 inline-Level 元素;
  • <a>里不可以嵌套交互式元素<a><button><select>等;
  • <p>里不可以嵌套块级元素<div><h1>~<h6><p><ul>/<ol>/<li><dl>/<dt>/<dd><form>等。
  • 15. 布尔值属性

    HTML5 规范中 disabledcheckedselected 等属性不用设置值。

    <input type="text" disabled>
    
    <input type="checkbox" value="1" checked>
    
    <select>
      <option value="1" selected>1</option>
    </select>

    16. 语义化

    没有 CSS 的 HTML 是一个语义系统而不是 UI 系统。

    通常情况下,每个标签都是有语义的,所谓语义就是你的衣服分为外套, 裤子,裙子,内裤等,各自有对应的功能和含义。所以你总不能把内裤套在脖子上吧。– 一丝

    此外语义化的 HTML 结构,有助于机器(搜索引擎)理解,另一方面多人协作时,能迅速了解开发者意图。

    标签 语义
    <p>
    段落
    <h1> <h2> <h3> ...
    标题
    <ul>
    无序列表
    <ol>
    有序列表
    <blockquote>
    大段引用
    <cite>
    一般引用
    <b>
    为样式加粗而加粗
    <strong>
    为强调内容而加粗
    <i>
    为样式倾斜而倾斜
    <em>
    为强调内容而倾斜
    code
    代码标识
    abbr
    缩写

    将你构建的页面当作一本书,将标签的语义对应的其功能和含义;

  • 书的名称:<h1>
  • 书的每个章节标题: <h2>
  • 章节内的文章标题: <h3>
  • 小标题/副标题: <h4> <h5> <h6>
  • 章节的段落: <p>
  • 四、CSS

    代码组织

  • 以组件为单位组织代码段;
  • 制定一致的注释规范;
  • 组件块和子组件块以及声明块之间使用一空行分隔,子组件块之间三空行分隔;
  • 如果使用了多个 CSS 文件,将其按照组件而非页面的形式分拆,因为页面会被重组,而组件只会被移动;
  • 良好的注释是非常重要的。请留出时间来描述组件(component)的工作方式、局限性和构建它们的方法。不要让你的团队其它成员 来猜测一段不通用或不明显的代码的目的。

    提示:通过配置编辑器,可以提供快捷键来输出一致认可的注释模式。

    /* ==========================================================================
       组件块
     ============================================================================ */
    
    /* 子组件块
     ============================================================================ */
    .selector {
      padding: 15px;
      margin-bottom: 15px;
    }
    
    
    
    /* 子组件块
     ============================================================================ */
    .selector-secondary {
      display: block; /* 注释*/
    }
    
    .selector-three {
      display: span;
    }

    Class 和 ID

  • 使用语义化、通用的命名方式;
  • 使用连字符 – 作为 ID、Class 名称界定符,不要驼峰命名法和下划线;
  • 避免选择器嵌套层级过多,尽量少于 3 级;
  • 避免选择器和 Class、ID 叠加使用;
  • 出于性能考量在没有必要的情况下避免元素选择器叠加 Class、ID 使用。

    元素选择器和 ID、Class 混合使用也违反关注分离原则。如果HTML标签修改了,就要再去修改 CSS 代码,不利于后期维护。

    /* Not recommended */
    .red {}
    .box_green {}
    .page .header .login #username input {}
    ul#example {}
    
    /* Recommended */
    #nav {}
    .box-video {}
    #username input {}
    #example {}

    声明块格式

  • 选择器分组时,保持独立的选择器占用一行;
  • 声明块的左括号 { 前添加一个空格;
  • 声明块的右括号 } 应单独成行;
  • 声明语句中的 : 后应添加一个空格;
  • 声明语句应以分号 ; 结尾;
  • 一般以逗号分隔的属性值,每个逗号后应添加一个空格;
  • rgb()rgba()hsl()hsla() 或 rect() 括号内的值,逗号分隔,但逗号后不添加一个空格;
  • 对于属性值或颜色参数,省略小于 1 的小数前面的 0 (例如,.5 代替 0.5-.5px 代替 -0.5px);
  • 十六进制值应该全部小写和尽量简写,例如,#fff 代替 #ffffff
  • 避免为 0 值指定单位,例如,用 margin: 0; 代替 margin: 0px;
  • /*  Not recommended  */
    .selector, .selector-secondary, .selector[type=text] {
      padding:15px;
      margin:0px 0px 15px;
      background-color:rgba(0, 0, 0, 0.5);
      box-shadow:0px 1px 2px #CCC,inset 0 1px 0 #FFFFFF
    }
    
    /* Recommended */
    .selector,
    .selector-secondary,
    .selector[type="text"] {
      padding: 15px;
      margin-bottom: 15px;
      background-color: rgba(0,0,0,.5);
      box-shadow: 0 1px 2px #ccc, inset 0 1px 0 #fff;
    }

    声明顺序

    相关属性应为一组,推荐的样式编写顺序

    1. Positioning
    2. Box model
    3. Typographic
    4. Visual

    由于定位(positioning)可以从正常的文档流中移除元素,并且还能覆盖盒模型(box model)相关的样式,因此排在首位。盒模型决定了组件的尺寸和位置,因此排在第二位。

    其他属性只是影响组件的内部(inside)或者是不影响前两组属性,因此排在后面。

    .declaration-order {
      /* Positioning */
      position: absolute;
      top: 0;
      right: 0;
      bottom: 0;
      left: 0;
      z-index: 100;
    
      /* Box model */
      display: block;
      box-sizing: border-box;
      width: 100px;
      height: 100px;
      padding: 10px;
      border: 1px solid #e5e5e5;
      border-radius: 3px;
      margin: 10px;
      float: right;
      overflow: hidden;
    
      /* Typographic */
      font: normal 13px "Helvetica Neue", sans-serif;
      line-height: 1.5;
      text-align: center;
    
      /* Visual */
      background-color: #f5f5f5;
      color: #fff;
      opacity: .8;
    
      /* Other */
      cursor: pointer;
    }

    引号使用

    url() 属性选择符、属性值使用双引号。

    /* Not recommended */
    @import url(//www.google.com/css/maia.css);
    
    html {
      font-family: 'open sans', arial, sans-serif;
    }
    
    /* Recommended */
    @import url("//www.google.com/css/maia.css");
    
    html {
      font-family: "open sans", arial, sans-serif;
    }
    
    .selector[type="text"] {
    
    }

    媒体查询(Media query)的位置

    将媒体查询放在尽可能相关规则的附近。不要将他们打包放在一个单一样式文件中或者放在文档底部。如果你把他们分开了,将来只会被大家遗忘。

    .element { ... }
    .element-avatar { ... }
    .element-selected { ... }
    
    @media (max-width: 768px) {
      .element { ...}
      .element-avatar { ... }
      .element-selected { ... }
    }

    不要使用 @import

    与 <link> 相比,@import 要慢很多,不光增加额外的请求数,还会导致不可预料的问题。

    替代办法:

  • 使用多个 元素;
  • 通过 Sass 或 Less 类似的 CSS 预处理器将多个 CSS 文件编译为一个文件;
  • 其他 CSS 文件合并工具;
  • 链接的样式顺序:

    a:link -> a:visited -> a:hover -> a:active(LoVeHAte)

    五、LESS

    代码组织

    代码按一下顺序组织:

    1. @import
    2. 变量声明
    3. 样式声明
    @import "mixins/size.less";
    
    @default-text-color: #333;
    
    .page {
      width: 960px;
      margin: 0 auto;
    }

    @import 语句

    @import 语句引用的文需要写在一对引号内,.less 后缀不得省略。引号使用 ' 和 " 均可,但在同一项目内需统一。

    /* Not recommended */
    @import "mixins/size";
    @import 'mixins/grid.less';
    
    /* Recommended */
    @import "mixins/size.less";
    @import "mixins/grid.less";

    混入(Mixin)

    1. 在定义 mixin 时,如果 mixin 名称不是一个需要使用的 className,必须加上括号,否则即使不被调用也会输出到 CSS 中。
    2. 如果混入的是本身不输出内容的 mixin,需要在 mixin 后添加括号(即使不传参数),以区分这是否是一个 className。
    /* Not recommended */
    .big-text {
      font-size: 2em;
    }
    
    h3 {
      .big-text;
      .clearfix;
    }
    
    /* Recommended */
    .big-text() {
      font-size: 2em;
    }
    
    h3 {
      .big-text(); /* 1 */
      .clearfix(); /* 2 */
    }

    避免嵌套层级过多

  • 将嵌套深度限制在2级。对于超过3级的嵌套,给予重新评估。这可以避免出现过于详实的CSS选择器。
  • 避免大量的嵌套规则。当可读性受到影响时,将之打断。推荐避免出现多于20行的嵌套规则出现。
  • 字符串插值

    变量可以用类似ruby和php的方式嵌入到字符串中,像@{name}这样的结构:
    @base-url: "http://assets.fnord.com";
    background-image: url("@{base-url}/images/bg.png");

    六、ES5

    类型” class=”reference-link”>类型

  • 原始值: 存取直接作用于它自身。
  • string
  • number
  • boolean
  • null
  • undefined
  • var foo = 1;
    var bar = foo;
    
    bar = 9;
    
    console.log(foo, bar); // => 1, 9
  • 复杂类型: 存取时作用于它自身值的引用。
  • object
  • array
  • function
  • var foo = [1, 2];
    var bar = foo;
    
    bar[0] = 9;
    
    console.log(foo[0], bar[0]); // => 9, 9

    对象” class=”reference-link”>对象

  • 使用直接量创建对象。
    // bad
    var item = new Object();
    
    // good
    var item = {};
  • 不要使用保留字作为键名,它们在 IE8 下不工作。更多信息
    // bad
    var superman = {
      default: { clark: 'kent' },
      private: true
    };
    
    // good
    var superman = {
      defaults: { clark: 'kent' },
      hidden: true
    };
  • 使用同义词替换需要使用的保留字。
    // bad
    var superman = {
      class: 'alien'
    };
    
    // bad
    var superman = {
      klass: 'alien'
    };
    
    // good
    var superman = {
      type: 'alien'
    };
  • 数组” class=”reference-link”>数组

  • 使用直接量创建数组。
    // bad
    var items = new Array();
    
    // good
    var items = [];
  • 向数组增加元素时使用 Array#push 来替代直接赋值。
    var someStack = [];
    
  • // bad
    someStack[someStack.length] = 'abracadabra';
    
    // good
    someStack.push('abracadabra');
    ```
  • 当你需要拷贝数组时,使用 Array#slice。jsPerf
    var len = items.length;
    var itemsCopy = [];
    var i;
    
    // bad
    for (i = 0; i < len; i++) {
      itemsCopy[i] = items[i];
    }
    
    // good
    itemsCopy = items.slice();
  • 使用 Array#slice 将类数组对象转换成数组。
    function trigger() {
      var args = Array.prototype.slice.call(arguments);
      ...
    }
  • 字符串” class=”reference-link”>字符串

  • 使用单引号 '' 包裹字符串。
    // bad
    var name = "Bob Parr";
    
    // good
    var name = 'Bob Parr';
    
    // bad
    var fullName = "Bob " + this.lastName;
    
    // good
    var fullName = 'Bob ' + this.lastName;
  • 超过 100 个字符的字符串应该使用连接符写成多行。
  • 注:若过度使用,通过连接符连接的长字符串可能会影响性能。jsPerf & 讨论.
    // bad
    var 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
    var 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
    var 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.';
  • 函数” class=”reference-link”>函数

  • 函数表达式:
    // 匿名函数表达式
    var anonymous = function() {
      return true;
    };
    
    // 命名函数表达式
    var named = function named() {
      return true;
    };
    
    // 立即调用的函数表达式(IIFE)
    (function () {
      console.log('Welcome to the Internet. Please follow me.');
    }());
  • 永远不要在一个非函数代码块(if、while 等)中声明一个函数,浏览器允许你这么做,但它们的解析表现不一致,正确的做法是:在块外定义一个变量,然后将函数赋值给它。
  • ```javascript
    // bad
    if (currentUser) {
      function test() {
        console.log('Nope.');
      }
    }
    
    // good
    var test;
    if (currentUser) {
      test = function test() {
        console.log('Yup.');
      };
    }
    ```
  • 永远不要把参数命名为 arguments。这将取代函数作用域内的 arguments 对象。
    // bad
    function nope(name, options, arguments) {
      // ...stuff...
    }
    
    // good
    function yup(name, options, args) {
      // ...stuff...
    }
  • 属性” class=”reference-link”>属性

  • 使用 . 来访问对象的属性。
    var luke = {
      jedi: true,
      age: 28
    };
    
    // bad
    var isJedi = luke['jedi'];
    
    // good
    var isJedi = luke.jedi;
  • 当通过变量访问属性时使用中括号 []
    var luke = {
      jedi: true,
      age: 28
    };
    
    function getProp(prop) {
      return luke[prop];
    }
    
    var isJedi = getProp('jedi');
  • 变量” class=”reference-link”>变量

  • 总是使用 var 来声明变量。不这么做将导致产生全局变量。我们要避免污染全局命名空间。
    // bad
    superPower = new SuperPower();
    
    // good
    var superPower = new SuperPower();
  • 使用 var 声明每一个变量。
    这样做的好处是增加新变量将变的更加容易,而且你永远不用再担心调换错 ; 跟 ,

    // bad
    var items = getItems(),
        goSportsTeam = true,
        dragonball = 'z';
    
    // bad
    // (跟上面的代码比较一下,看看哪里错了)
    var items = getItems(),
        goSportsTeam = true;
        dragonball = 'z';
    
    // good
    var items = getItems();
    var goSportsTeam = true;
    var dragonball = 'z';
  • 最后再声明未赋值的变量。当你需要引用前面的变量赋值时这将变的很有用。
    // bad
    var i, len, dragonball,
        items = getItems(),
        goSportsTeam = true;
    
    // bad
    var i;
    var items = getItems();
    var dragonball;
    var goSportsTeam = true;
    var len;
    
    // good
    var items = getItems();
    var goSportsTeam = true;
    var dragonball;
    var length;
    var i;
  • 在作用域顶部声明变量。这将帮你避免变量声明提升相关的问题。
    // bad
    function () {
      test();
      console.log('doing stuff..');
    
      //..other stuff..
    
      var name = getName();
    
      if (name === 'test') {
        return false;
      }
    
      return name;
    }
    
    // good
    function () {
      var name = getName();
    
      test();
      console.log('doing stuff..');
    
      //..other stuff..
    
      if (name === 'test') {
        return false;
      }
    
      return name;
    }
    
    // bad - 不必要的函数调用
    function () {
      var name = getName();
    
      if (!arguments.length) {
        return false;
      }
    
      this.setFirstName(name);
    
      return true;
    }
    
    // good
    function () {
      var name;
    
      if (!arguments.length) {
        return false;
      }
    
      name = getName();
      this.setFirstName(name);
    
      return true;
    }
  • 提升” class=”reference-link”>提升

  • 变量声明会提升至作用域顶部,但赋值不会。
    // 我们知道这样不能正常工作(假设这里没有名为 notDefined 的全局变量)
    function example() {
      console.log(notDefined); // => throws a ReferenceError
    }
    
    // 但由于变量声明提升的原因,在一个变量引用后再创建它的变量声明将可以正常工作。
    // 注:变量赋值为 `true` 不会提升。
    function example() {
      console.log(declaredButNotAssigned); // => undefined
      var declaredButNotAssigned = true;
    }
    
    // 解释器会把变量声明提升到作用域顶部,意味着我们的例子将被重写成:
    function example() {
      var declaredButNotAssigned;
      console.log(declaredButNotAssigned); // => undefined
      declaredButNotAssigned = true;
    }
  • 匿名函数表达式会提升它们的变量名,但不会提升函数的赋值。
    function example() {
      console.log(anonymous); // => undefined
    
      anonymous(); // => TypeError anonymous is not a function
    
      var anonymous = function () {
        console.log('anonymous function expression');
      };
    }
  • 命名函数表达式会提升变量名,但不会提升函数名或函数体。
    function example() {
      console.log(named); // => undefined
    
      named(); // => TypeError named is not a function
    
      superPower(); // => ReferenceError superPower is not defined
    
      var named = function superPower() {
        console.log('Flying');
      };
    }
    
    // 当函数名跟变量名一样时,表现也是如此。
    function example() {
      console.log(named); // => undefined
    
      named(); // => TypeError named is not a function
    
      var named = function named() {
        console.log('named');
      }
    }
  • 函数声明提升它们的名字和函数体。
    function example() {
      superPower(); // => Flying
    
      function superPower() {
        console.log('Flying');
      }
    }
  • 了解更多信息在 JavaScript Scoping & Hoisting by Ben Cherry.
  • 比较运算符 & 等号” class=”reference-link”>比较运算符 & 等号

  • 优先使用 === 和 !== 而不是 == 和 !=.
  • 条件表达式例如 if 语句通过抽象方法 ToBoolean 强制计算它们的表达式并且总是遵守下面的规则:
  • 对象 被计算为 true
  • Undefined 被计算为 false
  • Null 被计算为 false
  • 布尔值 被计算为 布尔的值
  • 数字 如果是 +0、-0 或 NaN 被计算为 false,否则为 true
  • 字符串 如果是空字符串 '' 被计算为 false,否则为 true
  • if ([0]) {
      // true
      // 一个数组就是一个对象,对象被计算为 true
    }
  • 使用快捷方式。
    // bad
    if (name !== '') {
      // ...stuff...
    }
    
    // good
    if (name) {
      // ...stuff...
    }
    
    // bad
    if (collection.length > 0) {
      // ...stuff...
    }
    
    // good
    if (collection.length) {
      // ...stuff...
    }
  • 了解更多信息在 Truth Equality and JavaScript by Angus Croll.