一些有用的 javascript 知识和代码规范

Author Avatar
Splendour 8月 15, 2015

类型 Types

  • 基础类型:When you access a primitive type you work directly on its value

    • string
    • number
    • boolean
    • null
    • undefined
      var foo = 1;
      var bar = foo;
      bar = 9;
      console.log(foo, bar); // => 1, 9
      
  • 复合类型:When you access a complex type you work on a reference to its value

    • object
    • array
    • function
      var foo = [1, 2];
      var bar = foo;
      bar[0] = 9;
      console.log(foo[0], bar[0]); // => 9, 9
      

对象 Objects

  • 创建对象
    // bad
    var item = new Object();
    // good
    var item = {};
    
  • 不要使用保留字作为 key
    // 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'
    };
    

数组 Arrays

  • 创建数组

    // bad
    var items = new Array();
    // good
    var items = [];
    
  • 不知道数组长度时,使用 push 函数添加元素

    var someStack = [];
    // bad
    someStack[someStack.length] = 'abracadabra';
    // good
    someStack.push('abracadabra');
    
  • 复制数组时使用 slice 函数

    var len = items.length;
    var itemsCopy = [];
    var i;
    // bad
    for (i = 0; i < len; i++) {
    itemsCopy[i] = items[i];
    }
    // good
    itemsCopy = items.slice();
    
  • 将一个数组类对象转化为数组,使用 slice 函数

    function list() {
    return Array.prototype.slice.call(arguments, 0);
    }
    var list1 = list(1, 2, 3);  // => [1, 2, 3]
    

字符串 Strings

  • 使用单引号

    // bad
    var name = "Bob Parr";
    // good
    var name = 'Bob Parr';
    
  • 字符串长度超过 80,应写成多行并使用 “ + ” 连接

  • 动态构建一个字符串时,使用 join 函数而不是 “ + ”

    var items;
    var messages;
    var length;
    var 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>';
    }
    

函数 Functions

  • 函数表达式

    // anonymous function expression
    var anonymous = function() {
    return true;
    };
    // named function expression
    var named = function named() {
    return true;
    };
    // immediately-invoked function expression (IIFE)
    (function() {
    console.log('Welcome to the Internet. Please follow me.');
    })();
    
  • Never declare a function in a non-function block (if, while, etc). Assign the function to a variable instead.

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

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

变量 Variables

  • 总是使用 var 来定义变量,否则会产生占用内存的全局变量

    // bad
    superPower = new SuperPower();
    // good
    var superPower = new SuperPower();
    
  • 每个变量使用一个 var 来定义

    // bad
    var items = getItems(),
      goSportsTeam = true,
      dragonball = 'z';
    // good
    var items = getItems();
    var goSportsTeam = true;
    var dragonball = 'z';
    
  • 未初始化的变量放在最后

    // 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;
    }
    return true;
    }
    // good
    function() {
    if (!arguments.length) {
      return false;
    }
    var name = getName();
    return true;
    }
    

提前 Hoisting

  • 变量声明在作用域内被提前,而赋值却留在原地

    function example() {
    console.log(notDefined); // => throws a ReferenceError
    }
    function example() {
    // Outputs: undefined
    console.log(declaredLater);
    declaredLater = "Now it's defined!"; //声明被提前到作用域开始处,赋值操作还在原地
    // Outputs: "Now it's defined!"
    console.log(declaredLater);
    }
    
  • 匿名函数变量被提前,函数定义却未被提前

    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() {
    superPower(); // => Flying
    function superPower() {
      console.log('Flying');
    }
    }
    

条件表达式和相等判断 Conditional Expressions & Equality

  • 使用 “ === ” 和 “ !== ” 替代 “ == ” 和 “ != ”

  • 表达式的值

    • Objects:true
    • Undefined:false
    • Null:false
    • Booleans:此 Boolean 的值
    • Numbers:0,-0,NaN 为 false,其他为 true
    • Strings:’ ‘ 为 false,其他为 true
  • 使用简单表达式

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

类型转换 Type Casting & Coercion

  • 值转字符串

    //  => this.reviewScore = 9;
    // bad
    var totalScore = this.reviewScore + '';
    // good
    var totalScore = '' + this.reviewScore;
    // bad
    var totalScore = '' + this.reviewScore + ' total score';
    // good
    var totalScore = this.reviewScore + ' total score';
    
  • 字符串转数字,使用 parseInt 函数,并且总是带上基数代表进制

    var inputValue = '4';
    // bad
    var val = new Number(inputValue);
    // bad
    var val = +inputValue;
    // bad
    var val = inputValue >> 0;
    // bad
    var val = parseInt(inputValue);
    // good
    var val = Number(inputValue);
    // good
    var val = parseInt(inputValue, 10);
    
  • 布尔值

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

事件 Events

  • 捕捉事件后,传递一个哈希而非单纯的数据
    // bad
    $(this).trigger('listingUpdated', listing.id);
    ...
    $(this).on('listingUpdated', function(e, listingId) {
    // do something with listingId
    });
    // good
    $(this).trigger('listingUpdated', { listingId : listing.id });
    ...
    $(this).on('listingUpdated', function(e, data) {
    // do something with data.listingId
    });