JavaScript Style Guide

作者: HenryDF | 来源:发表于2016-03-31 14:37 被阅读193次

最近公司热火朝天的学习reactjs,引入的最大的一个问题是,怎么写js code。好吧,大牛找了一个JavaScript Style Guide,是Airbnb的规范,英文的,导致对于其中的含义有时候拿不准。贴出来跟大家一起学习一下。

原文链接

7 Functions 函数

  • 7.1 Use function declarations instead of function expressions. jscs: requireFunctionDeclarations
    使用函数定义代替函数表达式。

    Why? Function declarations are named, so they're easier to identify in call stacks. Also, the whole body of a function declaration is hoisted, whereas only the reference of a function expression is hoisted. This rule makes it possible to always use Arrow Functions in place of function expressions.

    为什么?函数定义是有名字的,所以他们可以更容易的在调用栈中被识别出来。同样,方法定义的整个方法体被提前到最前面,而函数表达式只有对方法的引用会被提到最前。这条规则(7.1使用函数定义代替函数表达式)让总是使用箭头函数替换函数表达式变得具有可行性。(最后一句好难翻译。。。)

      // bad
      const foo = function () {
      };
    
      // good
      function foo() {
      }
    

    *自己的理解:当你使用函数表达式的时候,是为了将来在某个地方重用这个函数。而箭头函数在形式上更像函数定义,却可以像变量一样当成参数传递。
    *结合Hoist:当你使用函数表达式的时候,会有一段代码区间有产生错误的可能

    当没有Hoist的时候,我们必须在函数的定义之后才能调用。
    //eg.
    abc(); // throw reference error.
    function abc() {};
    abc(); // ok.
    有了Hoist之后,我们就可以这样写。
    //eg.
    abc(); //work
    function abc() {};
    但是,如果我们用函数表达式:
    eg. 1
    abc(); // throw type error.
    var abc = function () {};
    eg. 2
    abc(); // throw reference error.
    const abc = function () {};

      //only this will work
      var abc = function () {};
      abc();
    

    写的麻烦一点,也更现实一点:
    //untested
    $('btn').click(handleClick); // ok.
    function handleClick() {};

      $('btn').click(handleClick); // throw type error
      var handleClick = function () {};
    
      $('btn').click(handleClick); // throw reference error
      var handleClick = function () {};
    
  • 7.2 Immediately invoked function expressions: eslint: wrap-iife jscs: requireParenthesesAroundIIFE
    IIFE:必须用小括号包围。

    Why? An immediately invoked function expression is a single unit - wrapping both it, and its invocation parens, in parens, cleanly expresses this. Note that in a world with modules everywhere, you almost never need an IIFE.

    为什么?一个IIFE是一个完整的单位——包括它的定义和它的调用括号。把IIFE写在括号里,可以清楚的表达这个意思。注意,在一个到处都是在modules的世界里,你几乎用不到IIFE。

      // immediately-invoked function expression (IIFE)
      (function () {
        console.log('Welcome to the Internet. Please follow me.');
      }());
    

    *IIFE是有历史原因的,javascript是function scope,为了避免无意中修改到其他变量(var的副作用),所以出现了IIFE——将自己的代码封装到一个匿名的函数里,并且定义之后立即执行。参考链接:JavaScript-Scoping-and-Hoisting

  • 7.3 Never declare a function in a non-function block (if, while, etc). Assign the function to a variable instead. Browsers will allow you to do it, but they all interpret it differently, which is bad news bears. eslint: no-loop-func

    绝对不要在一个非函数语句块里定义一个函数(例如,if/while)。用把函数赋给一个变量代替。浏览器允许你这么做,但是它们实现起来却不一样,这是一个很糟糕的记忆。

  • 7.4 Note: ECMA-262 defines a block as a list of statements. A function declaration is not a statement. Read ECMA-262's note on this issue.

    注意,ECMA-262定义了“一个语句块是一组语句”。函数定义不是语句。读ECMA-262的Note关注这个问题。
    // bad
    if (currentUser) {
    function test() {
    console.log('Nope.');
    }
    }

      // good
      let test;
      if (currentUser) {
        test = () => {
          console.log('Yup.');
        };
      }
    
  • 7.5 Never name a parameter arguments. This will take precedence over the arguments object that is given to every function scope.

    不要把一个参数命名成arguments。这会覆盖每个函数都有的arguments。

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

    *函数默认会有一个叫arguments的参数,来代表所有的参数。

      x = findMax(1, 123, 500, 115, 44, 88);
    
      function findMax() {
          var i;
          var max = -Infinity;
          for (i = 0; i < arguments.length; i++) {
              if (arguments[i] > max) {
                  max = arguments[i];
              }
          }
          return max;
      }
    
  • 7.6 Never use arguments, opt to use rest syntax ... instead. prefer-rest-params

永远不要用arguments,用rest语法...代替。

_Why? ... is explicit about which arguments you want pulled. Plus, rest arguments are a real Array, and not merely Array-like like arguments.

为什么?...能明确的标示哪一个参数你想展开。另外,rest参数是一个真实的数组,而不是像arguments那样,只是一个类似数组的变量。_

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

    // good
    function concatenateAll(...args) {
        return args.join('');
    }
  • 7.7 Use default parameter syntax rather than mutating function arguments.

用默认参数的语法,而不是修改函数的参数。

    // really bad
    function handleThings(opts) {
        // No! We shouldn't mutate function arguments.
        // Double bad: if opts is falsy it'll be set to an object which may
        // be what you want but it can introduce subtle bugs.
        opts = opts || {};
        // ...
    }

    // still bad
    function handleThings(opts) {
        if (opts === void 0) {
            opts = {};
        }
        // ...
    }

    // good
    function handleThings(opts = {}) {
        // ...
    }
  • 7.8 Avoid side effects with default parameters.

避免在默认参数中的副作用。不要在默认参数中修改外部的变量 参考

Why? They are confusing to reason about.
为什么?因为会让你迷惑为什么会这样。

    var b = 1;
    // bad
    function count(a = b++) {
        console.log(a);
    }
    count();  // 1
    count();  // 2
    count(3); // 3
    count();  // 3
  • 7.9 Always put default parameters last.

总是把默认参数放到最后。

    // bad
    function handleThings(opts = {}, name) {
        // ...
    }

    // good
    function handleThings(name, opts = {}) {
        // ...
    }
  • 7.10 Never use the Function constructor to create a new function.

永远不要用函数构建器去创建一个新的函数。

Why? Creating a function in this way evaluates a string similarly to eval(), which opens vulnerabilities.
为什么?用这种方法去创建一个函数就像用 eval() ,非常容易被攻击。

  • 7.11 Spacing in a function signature.

在函数签名中保留空格。

Why? Consistency is good, and you shouldn’t have to add or remove a space when adding or removing a name.
为什么,因为这样统一性很好。并且你在添加或删除名字的时候去添加、删除空格。

// bad
const f = function(){};
const g = function (){};
const h = function() {};

    // good
    const x = function () {};
    const y = function a() {};
  • 7.12 Never mutate parameters. eslint: no-param-reassign

永远不要修改参数。

Why? Manipulating objects passed in as parameters can cause unwanted variable side effects in the original caller.
为什么?操作参数里传进来的对象能导致调用者中不想要的副作用变化。

    // bad
    function f1(obj) {
        obj.key = 1;
    };

    // good
    function f2(obj) {
        const key = Object.prototype.hasOwnProperty.call(obj, 'key') ? obj.key : 1;
    };
  • 7.13 Never reassign parameters. eslint: no-param-reassign

永远不要重新给参数赋值。

Why? Reassigning parameters can lead to unexpected behavior, especially when accessing the arguments object. It can also cause optimization issues, especially in V8.
为什么?重新给参数赋值能导致不可预期的行为,特别是访问arguments对象。这么做同样能引起优化问题,特别是在V8引擎中。

    // bad
    function f1(a) {
        a = 1;
    }

    function f2(a) {
        if (!a) { a = 1; }
    }

    // good
    function f3(a) {
        const b = a || 1;
    }

    function f4(a = 1) {
    }

相关文章

网友评论

    本文标题:JavaScript Style Guide

    本文链接:https://www.haomeiwen.com/subject/lwvelttx.html