JavaScript语言教程

Javascript语法指南大全

目录

  1. 类型
  2. 对象
  3. 数组
  4. 字符串
  5. 函数
  6. 属性
  7. 变量
  8. 声明提升
  9. 条件表达式
  10. 注解

类型

  • 初始类型: 当你访问初始类型,可以直接使用其值。

    • string字符串类型
    • number类型
    • boolean类型
    • null类型
    • undefined类型

    var foo = 1,     

    bar = foo;   

    bar = 9;   

    console.log(foo, bar); // => 1, 9 

  • 复杂: 当你访问复杂类型,你使用的是其值的引用。
    • object对象
    • array数组
    • function函数

    var foo = [1, 2],

        bar = foo;

     

    bar[0] = 9;

     

    console.log(foo[0], bar[0]); // => 9, 9

⬆ back to top

对象

  • 使用literal字面语法创建对象.

    // bad

    var item = new Object();

     

    // good

    var item = {};

  • 不用使用 保护词语reserved words 作为代码,在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'

    };

⬆ back to top

数组Arrays

  • 使用文字语法创建数组

    // bad 
    var items = new Array();
    // good
    var items = [];
  • 如果你不知道数组的长度,使用Array#push.
    var someStack = [];    
    // bad
    someStack[someStack.length] = 'abracadabra';
    // good
    someStack.push('abracadabra');
  • 拷贝数组时使用Array#slice
    var len = items.length,     
    itemsCopy = [],
    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); ...
    }

⬆ back to top

字符串Strings

  • 字符串用单引号"

    // bad  
    var name = "Bob Parr"; //双引号
    // good
    var name = 'Bob Parr'; //单引号
    // bad
    var fullName = "Bob " + this.lastName;
    // good
    var fullName = 'Bob ' + this.lastName;
  • 超过80字符的字符串应该多行编写,使用字符串连接。
  • 如果过度使用,长字符串连接可能会影响性能
    // 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.';
  • 当通过编程建立一个字符串,使用数组Array#join加入而不是字符串连接。
    var items,     
    messages,
    length,
    i;
    messages = [{ state: 'success', message: 'This one worked.' },
    { state: 'success', message: 'This one worked as well.' },
    { state: 'error', message: 'This one did not work.' }];

    length = messages.length;

    // bad
    function inbox(messages) {
    items = '<ul>';
    for (i = 0; i < length; i++) {
    items += '<li>' + messages[i].message + '</li>'; }
    return items + '</ul>';
    }
    // good
    function inbox(messages) {
    items = [];
    for (i = 0; i < length; i++) {
    items[i] = messages[i].message;
    }
    return '<ul><li>' + items.join('</li><li>') + '</li></ul>';
    }

⬆ back to top

函数Function

  • 函数表达式:

    //  匿名函数
     var anonymous = function() {    return true;  };    
    
    // 有名函数
     var named = function named() {    return true;  };    
    
    //立即调用的函数
    (function() { 
    console.log('Welcome to the Internet. Please follow me.');
    })();
  • 不要在非函数块中定义一个函数,应该分配函数到一个变量。虽然浏览器可能允许你这么做,但是不同浏览器有不同的解释执行方式,这是导致运行不稳定原因。

  • 注意: ECMA-262 定义一个代码块作为statement集合. 但是一个函数声明不是一个statement. Read ECMA-262's note on this issue.
    // bad 
     if (currentUser) {
        function test() {
          console.log('Nope.');
        }
      }
     // good  
    var test;  
    if (currentUser) {
        test = function test() {      console.log('Yup.');    };
      }  
  • 不要给一个参数取名为arguments,
    // bad
    function nope(name, options, arguments) {    // ...stuff...  } 
      // good  
    function yup(name, options, args) {    // ...stuff...  }  

⬆ back to top

属性Properties

  • 访问属性时使用点符号

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

⬆ back to top

变量Variables

  • 总是使用var定义变量,不这样做将导致全局变量。我们要避免污染全局命名空间。

    // bad  
    superPower = new SuperPower();    
    // good  
    var superPower = new SuperPower();  
  • 使用一个var声明多个变量,然后每行声明一个个变量。.
    // bad  
    var items = getItems();  
    var goSportsTeam = true;  
    var dragonball = 'z';    
    // good  
    var items = getItems(), 
         goSportsTeam = true,
          dragonball = 'z';  
  • 最后声明未赋值的变量,如果你需要依赖之前已经分配的变量分配变量时这会有帮助。
    // bad  
    var i, len, dragonball,      
        items = getItems(),      
        goSportsTeam = true;    
    
    // bad  
    var i, items = getItems(),
          dragonball,
          goSportsTeam = true,
          len;
    
    // good  
    var items = getItems(),      
        goSportsTeam = true,      
        dragonball,      
        length,      
        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;

      }

     

      return true;

    }

     

    // good

    function() {

      if (!arguments.length) {

        return false;

      }

     

      var name = getName();

     

      return true;

    }

     

⬆ back to top

变量提升Hoisting

  • 变量声明能够升级到作用域顶部,而他们的分配值则不可以.

         

    // 下面不会正常工作(假设没有notDefined这个全局变量)

    function example() {

      console.log(notDefined); // => 抛出错误ReferenceError

    }

     

    // 当你引用一个变量后再创建变量的声明会正常工作

    //因为变量提升的原因。但是分配值`true`不会提升

    function example() {

      console.log(declaredButNotAssigned); // => 未定义

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

      };

    }

     

    // the same is true when the function name

    // is the same as the variable name.

    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

⬆ back to top

条件表达式与等式

  • 使用 === 和 !==,不用 == 和 !=.
  • 条件表达式使用ToBoolean方法被强迫转换,遵循下面规则:
    • Objects 是 true
    • Undefined 等同 false
    • Null 是 false
    • Booleans 是 boolean的值
    • Numbers 是在 +0, -0, or NaN为false , 其他为 true
    • Strings 如果有空字符串''是 false ,否则是true
         

    if ([0]) {

      // true

      // 一个数组array是一个对象,对象将等同于true

    }

  • 使用快捷方式shortcuts.
         

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

⬆ back to top

块Blocks

  • 多行代码块使用花括号.

         

    // bad

    if (test)

      return false;

     

    // good

    if (test) return false;

     

    // good

    if (test) {

      return false;

    }

     

    // bad

    function() { return false; }

     

    // good

    function() {

      return false;

    }

⬆ back to top

注释

  • 使用 /** ... */ 多行注解 包括描述,为所有指定类型和值参数和返回值。

         

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

    }

  • 使用// 单行注释,
         

    // bad

    var active = true;  // is current tab

     

    // good

    // is current tab

    var active = true;

     

    // bad

    function getType() {

      console.log('fetching type...');

      // set the default type to 'no type'

      var type = this._type || 'no type';

     

      return type;

    }

     

    // good

    function getType() {

      console.log('fetching type...');

     

      // set the default type to 'no type'

      var type = this._type || 'no type';

     

      return type;

    }

  • 用 // FIXME: 标注问题
         

    function Calculator() {

     

      // FIXME: shouldn't use a global here

      total = 0;

     

      return this;

    }

  • 使用// TODO: 标注问题的解决
         

    function Calculator() {

     

      // TODO: total should be configurable by an options param

      this.total = 0;

     

      return this;

    }

⬆ back to top

Node.js最佳实践