Write JavaScript in a more sensible way

directory

type

  • Raw value: Access acts directly on itself.

    • string
    • number
    • boolean
    • null
    • undefined
    var foo = 1;
    var bar = foo;
    
    bar = 9;
    
    console.log(foo, bar); 
    Copy the code
  • Complex type: A reference that operates on its own value when accessed.

    var foo = [1, 2];
    var bar = foo;
    
    bar[0] = 9;
    
    console.log(foo[0], bar[0]); 
    Copy the code

Siep back to the top

object

  • Create objects using direct quantities.

    
    var item = new Object();
    
    
    var item = {};
    Copy the code
  • Do not use reserved words as key names, they do not work under IE8. More information.

    
    var superman = {
      default: { clark: 'kent' },
      private: true
    };
    
    
    var superman = {
      defaults: { clark: 'kent' },
      hidden: true
    };
    Copy the code
  • Use synonyms to replace reserved words that you want to use.

    
    var superman = {
      class: 'alien'
    };
    
    
    var superman = {
      klass: 'alien'
    };
    
    
    var superman = {
      type: 'alien'
    };
    Copy the code

Siep back to the top

An array of

  • Create arrays using direct quantities.

    
    var items = new Array();
    
    
    var items = [];
    Copy the code
  • Use Array#push instead of direct assignment when adding elements to an array.

    “`javascript var someStack = [];

someStack[someStack.length] = 'abracadabra'; someStack.push('abracadabra'); ` ` `Copy the code
  • When you need to copy an array, use Array#slice. jsPerf

    var len = items.length;
    var itemsCopy = [];
    var i;
    
    
    for (i = 0; i < len; i++) {
      itemsCopy[i] = items[i];
    }
    
    
    itemsCopy = items.slice();
    Copy the code
  • Convert an array-like object to an array using Array#slice.

    function trigger() { var args = Array.prototype.slice.call(arguments); . }Copy the code

Siep back to the top

string

  • Wrap strings with single quotation marks.

    
    var name = "Bob Parr";
    
    
    var name = 'Bob Parr';
    
    
    var fullName = "Bob " + this.lastName;
    
    
    var fullName = 'Bob ' + this.lastName;
    Copy the code
  • Strings of more than 100 characters should be written on multiple lines using a hyphen.

  • Note: Long strings concatenated by hyphens can affect performance if overused. JsPerf & discussion.

    
    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.';
    
    
    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.';
    
    
    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.';
    Copy the code
  • Programmatically generated strings join using Array#join instead of using a hyphen. Especially under IE: jsPerf.

    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;
    
    
    function inbox(messages) {
      items = '
            
      '
    ; for (i = 0; i < length; i++) { items += '
  • '
  • + messages[i].message + ''; } return items + ''; } function inbox(messages) { items = []; for (i = 0; i < length; i++) { items[i] = '
  • '
  • + messages[i].message + ''; } return '
      '
    + items.join('') + ''; } Copy the code

Siep back to the top

function

  • Function expression:

    var anonymous = function() { return true; }; var named = function named() { return true; }; (function () { console.log('Welcome to the Internet. Please follow me.'); } ());Copy the code
  • Never declare a function in a non-functional block of code (if, while, etc.) and assign that function to a variable. Browsers let you do this, but they parse inconsistently.

  • Note: ECMA-262 defines a block as a set of statements. Function declarations are not statements. Read a description of this problem with ECMA-262.

    
    if (currentUser) {
      function test() {
        console.log('Nope.');
      }
    }
    
    
    var test;
    if (currentUser) {
      test = function test() {
        console.log('Yup.');
      };
    }
    Copy the code
  • Never name arguments as arguments. This replaces the Arguments object in the function scope.

    
    function nope(name, options, arguments) {
      
    }
    
    
    function yup(name, options, args) {
      
    }
    Copy the code

Siep back to the top

attribute

  • Use. To access the properties of the object.

    var luke = {
      jedi: true,
      age: 28
    };
    
    
    var isJedi = luke['jedi'];
    
    
    var isJedi = luke.jedi;
    Copy the code
  • Use brackets [] when accessing properties through variables.

    var luke = {
      jedi: true,
      age: 28
    };
    
    function getProp(prop) {
      return luke[prop];
    }
    
    var isJedi = getProp('jedi');
    Copy the code

Siep back to the top

variable

  • Always use var to declare variables. Failure to do so will result in global variables. We want to avoid contaminating the global namespace.

    
    superPower = new SuperPower();
    
    
    var superPower = new SuperPower();
    Copy the code
  • Declare each variable using var. The advantage of this is that it’s much easier to add new variables, and you never have to worry about transposing them wrong; With that.

    
    var items = getItems(),
        goSportsTeam = true,
        dragonball = 'z';
    
    
    
    var items = getItems(),
        goSportsTeam = true;
        dragonball = 'z';
    
    
    var items = getItems();
    var goSportsTeam = true;
    var dragonball = 'z';
    Copy the code
  • Finally, unassigned variables are declared. This can be useful when you need to reference previous variable assignments.

    
    var i, len, dragonball,
        items = getItems(),
        goSportsTeam = true;
    
    
    var i;
    var items = getItems();
    var dragonball;
    var goSportsTeam = true;
    var len;
    
    
    var items = getItems();
    var goSportsTeam = true;
    var dragonball;
    var length;
    var i;
    Copy the code
  • Declare variables at the top of the scope. This will help you avoid problems associated with variable declaration promotion.

    function () { test(); console.log('doing stuff.. '); var name = getName(); if (name === 'test') { return false; } return name; } function () { var name = getName(); test(); console.log('doing stuff.. '); if (name === 'test') { return false; } return name; } function () { var name = getName(); if (! arguments.length) { return false; } this.setFirstName(name); return true; } function () { var name; if (! arguments.length) { return false; } name = getName(); this.setFirstName(name); return true; }Copy the code

Siep back to the top

ascension

  • Variable declarations are promoted to the top of scope, but assignments are not.

    
    function example() {
      console.log(notDefined); 
    }
    
    
    
    function example() {
      console.log(declaredButNotAssigned); 
      var declaredButNotAssigned = true;
    }
    
    
    function example() {
      var declaredButNotAssigned;
      console.log(declaredButNotAssigned); 
      declaredButNotAssigned = true;
    }
    Copy the code
  • Anonymous function expressions promote their variable names, but not function assignments.

    function example() {
      console.log(anonymous); 
    
      anonymous(); 
    
      var anonymous = function () {
        console.log('anonymous function expression');
      };
    }
    Copy the code
  • Named function expressions promote variable names, but not function names or function bodies.

    function example() { console.log(named); named(); superPower(); var named = function superPower() { console.log('Flying'); }; } function example() { console.log(named); named(); var named = function named() { console.log('named'); }}Copy the code
  • Function declarations promote their names and function bodies.

    function example() { superPower(); function superPower() { console.log('Flying'); }}Copy the code
  • Learn more in JavaScript Scoping & Collieries by Ben Cherry.

Siep back to the top

The comparison operator & equals

  • Preferred to use= = =! = =Rather than= =! =.
  • Conditional expressions such as if statements force their expressions to be evaluated through the abstract method ToBoolean and always follow the following rule:

    • The object is evaluated to true
    • Undefined evaluates to false
    • Null is computed to false
    • Boolean values are computed as Boolean values
    • A number is computed to false if it is +0, -0, or NaN, and to true otherwise
    • stringIf it’s an empty string' 'Be calculated asfalse, or fortrue
    if ([0]) {
      
      
    }
    Copy the code
  • Use shortcuts.

    if (name ! == '') { } if (name) { } if (collection.length > 0) { } if (collection.length) { }Copy the code
  • Learn more in Truth Equality and JavaScript by Angus Croll.

Siep back to the top

block

  • Wrap all multi-line code blocks with braces.

    
    if (test)
      return false;
    
    
    if (test) return false;
    
    
    if (test) {
      return false;
    }
    
    
    function () { return false; }
    
    
    function () {
      return false;
    }
    Copy the code
  • If you use multi-line blocks with if and else, place the else on the same line as the if block closes the parentheses.

    
    if (test) {
      thing1();
      thing2();
    }
    else {
      thing3();
    }
    
    
    if (test) {
      thing1();
      thing2();
    } else {
      thing3();
    }
    Copy the code

Siep back to the top

annotation

  • Use the / * *… */ as a multi-line comment. Contains descriptions, types and values specifying all parameters, and return values.

    
    
    
    
    
    
    function make(tag) {
    
      
    
      return element;
    }
    
    
    
    function make(tag) {
    
      
    
      return element;
    }
    Copy the code
  • Use // as a single-line comment. Use a single line comment on a separate line above the comment object. Insert blank lines before comments.

    var active = true; var active = true; function getType() { console.log('fetching type... '); var type = this.type || 'no type'; return type; } function getType() { console.log('fetching type... '); var type = this.type || 'no type'; return type; }Copy the code
  • Adding FIXME or TODO prefixes to comments can help other developers quickly understand that this is a problem that needs to be reviewed, or provide a workaround for a feature that needs to be implemented. This will be different from common annotations because they are operational. Use FIXME — need to figure this out or TODO — need to Implement.

  • Use // FIXME: to flag problems.

    function Calculator() {
    
      
      total = 0;
    
      return this;
    }
    Copy the code
  • Use // TODO: note the solution to the problem.

    function Calculator() {
    
      
      this.total = 0;
    
      return this;
    }
    Copy the code

Siep back to the top

blank

  • Use 2 Spaces for indentation.

    Function () {∙∙∙var name; } function () {∙var name; } function () {∙∙var name; }Copy the code
  • Place a space before the braces.

    
    function test(){
      console.log('test');
    }
    
    
    function test() {
      console.log('test');
    }
    
    
    dog.set('attr',{
      age: '1 year',
      breed: 'Bernese Mountain Dog'
    });
    
    
    dog.set('attr', {
      age: '1 year',
      breed: 'Bernese Mountain Dog'
    });
    Copy the code
  • Place a space before the parentheses of control statements (if, while, etc.). In function calls and declarations, do not prefix function argument lists with Spaces.

    if(isJedi) { fight (); } if (isJedi) { fight(); } function fight () { console.log ('Swooosh! '); } function fight() { console.log('Swooosh! '); }Copy the code
  • Use Spaces to separate the operators.

    
    var x=y+5;
    
    
    var x = y + 5;
    Copy the code
  • Insert a blank line at the end of the file.

    
    (function (global) {
      
    })(this);
    Copy the code
    (function (global) { })(this); ↵ ↵Copy the code
    (function (global) { })(this); ↵Copy the code
  • Indent when using long method chains. Use the preceding dot. Emphasize that this is a method call and not a new statement.

    
    $('#items').find('.selected').highlight().end().find('.open').updateCount();
    
    
    $('#items').
      find('.selected').
        highlight().
        end().
      find('.open').
        updateCount();
    
    
    $('#items')
      .find('.selected')
        .highlight()
        .end()
      .find('.open')
        .updateCount();
    
    
    var leds = stage.selectAll('.led').data(data).enter().append('svg:svg').classed('led', true)
        .attr('width', (radius + margin) * 2).append('svg:g')
        .attr('transform', 'translate(' + (radius + margin) + ',' + (radius + margin) + ')')
        .call(tron.led);
    
    
    var leds = stage.selectAll('.led')
        .data(data)
      .enter().append('svg:svg')
        .classed('led', true)
        .attr('width', (radius + margin) * 2)
      .append('svg:g')
        .attr('transform', 'translate(' + (radius + margin) + ',' + (radius + margin) + ')')
        .call(tron.led);
    Copy the code
  • Insert blank lines at the end of the block and before the new statement.

    
    if (foo) {
      return bar;
    }
    return baz;
    
    
    if (foo) {
      return bar;
    }
    
    return baz;
    
    
    var obj = {
      foo: function () {
      },
      bar: function () {
      }
    };
    return obj;
    
    
    var obj = {
      foo: function () {
      },
    
      bar: function () {
      }
    };
    
    return obj;
    Copy the code

Siep back to the top

The comma

  • First line comma: Not required.

    
    var story = [
        once
      , upon
      , aTime
    ];
    
    
    var story = [
      once,
      upon,
      aTime
    ];
    
    
    var hero = {
        firstName: 'Bob'
      , lastName: 'Parr'
      , heroName: 'Mr. Incredible'
      , superPower: 'strength'
    };
    
    
    var hero = {
      firstName: 'Bob',
      lastName: 'Parr',
      heroName: 'Mr. Incredible',
      superPower: 'strength'
    };
    Copy the code
  • Extra end-of-line comma: not required. Doing so can cause problems in IE6/7 and IE9 weird mode. Also, extra commas increase the array length in some ES3 implementations. It has been clarified in ES5:

    Edition 5 clarifies the fact that a trailing comma at the end of an ArrayInitialiser does not add to the length of the array. This is not a semantic change from Edition 3 but some implementations may have previously misinterpreted this.

    
    var hero = {
      firstName: 'Kevin',
      lastName: 'Flynn',
    };
    
    var heroes = [
      'Batman',
      'Superman',
    ];
    
    
    var hero = {
      firstName: 'Kevin',
      lastName: 'Flynn'
    };
    
    var heroes = [
      'Batman',
      'Superman'
    ];
    Copy the code

Siep back to the top

A semicolon

  • Use a semicolon.

    (function () { var name = 'Skywalker' return name })() (function () { var name = 'Skywalker'; return name; }) (); ; (function () { var name = 'Skywalker'; return name; }) ();Copy the code

    Learn more.

Siep back to the top

Type conversion

  • Perform a type conversion at the beginning of a statement.
  • String:

    
    
    
    var totalScore = this.reviewScore + '';
    
    
    var totalScore = '' + this.reviewScore;
    
    
    var totalScore = '' + this.reviewScore + ' total score';
    
    
    var totalScore = this.reviewScore + ' total score';
    Copy the code
  • Using parseInt to convert numbers always takes the cardinality of the type conversion.

    var inputValue = '4';
    
    
    var val = new Number(inputValue);
    
    
    var val = +inputValue;
    
    
    var val = inputValue >> 0;
    
    
    var val = parseInt(inputValue);
    
    
    var val = Number(inputValue);
    
    
    var val = parseInt(inputValue, 10);
    Copy the code
  • If for some reason parseInt becomes a bottleneck in what you’re doing and you need to use bit-manipulation to solve a performance problem, leave a comment stating why and why you’re doing it.

    
    
    var val = inputValue >> 0;
    Copy the code
  • Note: Be careful with bitwise operators. Numbers are treated as 64-bit values, but bitwise operators always return 32-bit integers (source). Bitwise operations can also cause unexpected behavior when dealing with integer values greater than 32 bits. The discussion. The largest 32-bit integer is 2,147,483,647:

    2147483647 >> 0 
    2147483648 >> 0 
    2147483649 >> 0 
    Copy the code
  • Boolean:

    var age = 0; var hasAge = new Boolean(age); var hasAge = Boolean(age); var hasAge = !! age;Copy the code

Siep back to the top

Naming rules

  • Avoid single-letter naming. Naming should be descriptive.

    
    function q() {
      
    }
    
    
    function query() {
      
    }
    Copy the code
  • Use camel case naming of objects, functions, and instances.

    
    var OBJEcttsssss = {};
    var this_is_my_object = {};
    var o = {};
    function c() {}
    
    
    var thisIsMyObject = {};
    function thisIsMyFunction() {}
    Copy the code
  • Use PASCAL names for constructors or classes.

    
    function user(options) {
      this.name = options.name;
    }
    
    var bad = new user({
      name: 'nope'
    });
    
    
    function User(options) {
      this.name = options.name;
    }
    
    var good = new User({
      name: 'yup'
    });
    Copy the code
  • Do not use an underscore prefix/suffix.

    Why is that? JavaScript has no concept of private properties or methods. While it is common sense to use underscores to mean “private,” in fact these attributes are completely public and are themselves part of your public interface. This habit may lead developers to mistakenly believe that changing it won’t break or doesn’t require testing. Long story short: If you want something to be “private,” it must not be explicitly proposed.

    
    this.__firstName__ = 'Panda';
    this.firstName_ = 'Panda';
    this._firstName = 'Panda';
    
    
    this.firstName = 'Panda';
    Copy the code
  • Do not save a reference to this. Using Function# bind.

    
    function () {
      var self = this;
      return function () {
        console.log(self);
      };
    }
    
    
    function () {
      var that = this;
      return function () {
        console.log(that);
      };
    }
    
    
    function () {
      var _this = this;
      return function () {
        console.log(_this);
      };
    }
    
    
    function () {
      return function () {
        console.log(this);
      }.bind(this);
    }
    Copy the code
  • Give the function a name. This is very helpful when doing stack traces.

    
    var log = function (msg) {
      console.log(msg);
    };
    
    
    var log = function log(msg) {
      console.log(msg);
    };
    Copy the code
  • Note: IE8 and below have some weird handling of named function expressions. Learn more at Kangax.github. IO /nfe/.

  • If your file exports a class, your file name should be exactly the same as the class name.

    
    class CheckBox {
      
    }
    module.exports = CheckBox;
    
    
    
    var CheckBox = require('./checkBox');
    
    
    var CheckBox = require('./check_box');
    
    
    var CheckBox = require('./CheckBox');
    Copy the code

Siep back to the top

accessor

  • Property access functions are not required.
  • Use getVal() and setVal(‘hello’) if you need to access functions.

    
    dragon.age();
    
    
    dragon.getAge();
    
    
    dragon.age(25);
    
    
    dragon.setAge(25);
    Copy the code
  • If the attribute is a Boolean value, use isVal() or hasVal().

    if (! dragon.age()) { return false; } if (! dragon.hasAge()) { return false; }Copy the code
  • It’s ok to create get() and set() functions, but keep them consistent.

    function Jedi(options) {
      options || (options = {});
      var lightsaber = options.lightsaber || 'blue';
      this.set('lightsaber', lightsaber);
    }
    
    Jedi.prototype.set = function set(key, val) {
      this[key] = val;
    };
    
    Jedi.prototype.get = function get(key) {
      return this[key];
    };
    Copy the code

Siep back to the top

The constructor

  • Assign methods to object prototypes instead of overwriting them with a new object. Overwriting the stereotype causes inheritance problems: rewriting the stereotype overwrites the original!

    function Jedi() { console.log('new jedi'); } Jedi.prototype = { fight: function fight() { console.log('fighting'); }, block: function block() { console.log('blocking'); }}; Jedi.prototype.fight = function fight() { console.log('fighting'); }; Jedi.prototype.block = function block() { console.log('blocking'); };Copy the code
  • Methods can return this to implement method chained usage.

    
    Jedi.prototype.jump = function jump() {
      this.jumping = true;
      return true;
    };
    
    Jedi.prototype.setHeight = function setHeight(height) {
      this.height = height;
    };
    
    var luke = new Jedi();
    luke.jump(); 
    luke.setHeight(20); 
    
    
    Jedi.prototype.jump = function jump() {
      this.jumping = true;
      return this;
    };
    
    Jedi.prototype.setHeight = function setHeight(height) {
      this.height = height;
      return this;
    };
    
    var luke = new Jedi();
    
    luke.jump()
      .setHeight(20);
    Copy the code
  • It’s ok to write a custom toString() method, but make sure it works and doesn’t cause side effects.

    function Jedi(options) {
      options || (options = {});
      this.name = options.name || 'no name';
    }
    
    Jedi.prototype.getName = function getName() {
      return this.name;
    };
    
    Jedi.prototype.toString = function toString() {
      return 'Jedi - ' + this.getName();
    };
    Copy the code

Siep back to the top

The event

  • When attaching data to an event (whether a DOM event or a private event), pass in a hash instead of the original value. This allows later contributors to add more data to the event data without having to find and update every handler of the event. For example, bad writing:

    $(this).trigger('listingUpdated', listing.id); . $(this).on('listingUpdated', function (e, listingId) { });Copy the code

    Better written:

    $(this).trigger('listingUpdated', { listingId : listing.id }); . $(this).on('listingUpdated', function (e, data) { });Copy the code

    Siep back to the top

The module

  • Modules should start with!Start. This ensures that when a bad module forgets to include the last semicolon, it will not generate an error after merging the code into production.Detailed instructions
  • The files should be named in camel shape and placed in a folder with the same name as the exported file.
  • Add a name callednoConflict()To set the exported module to the previous version and return it.
  • Always declare ‘use strict’ at the top of the module; .

    ! function (global) { ; var previousFancyInput = global.FancyInput; function FancyInput(options) { this.options = options || {}; } FancyInput.noConflict = function noConflict() { global.FancyInput = previousFancyInput; return FancyInput; }; global.FancyInput = FancyInput; }(this);Copy the code

Siep back to the top

jQuery

  • Use $to prefix the variable name that stores the jQuery object.

    
    var sidebar = $('.sidebar');
    
    
    var $sidebar = $('.sidebar');
    Copy the code
  • Cache jQuery queries.

    
    function setSidebar() {
      $('.sidebar').hide();
    
      
    
      $('.sidebar').css({
        'background-color': 'pink'
      });
    }
    
    
    function setSidebar() {
      var $sidebar = $('.sidebar');
      $sidebar.hide();
    
      
    
      $sidebar.css({
        'background-color': 'pink'
      });
    }
    Copy the code
  • Use a cascading $(‘.sidebar ul’) or parent element > child element $(‘.sidebar > ul’) for DOM queries. jsPerf

  • Use find for scoped jQuery object queries.

    
    $('ul', '.sidebar').hide();
    
    
    $('.sidebar').find('ul').hide();
    
    
    $('.sidebar ul').hide();
    
    
    $('.sidebar > ul').hide();
    
    
    $sidebar.find('ul').hide();
    Copy the code

Siep back to the top

ECMAScript 5 compatibility

Siep back to the top

test

  • Yup.

    function () {
      return true;
    }
    Copy the code

Siep back to the top

performance

Siep back to the top

resources

Recommended reading

Other Style Guides

Other style

Further reading

Siep back to the top

Who is using

This is a list of organizations that use this style guide. Send us a pull Request or open an issue and let us add you to the list.

translation

This style guide is also available in other languages:

JavaScript Style guide notes

Talk to us about JavaScript

contributors

The license

(The MIT License)

Copyright (c) 2014 Airbnb

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the ‘Software’), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED ‘AS IS’, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

Siep back to the top

Please reserve the address of this article for reprint:
Best use javascript coding specification Chinese version (transferred from Airbnb JS Coding Specification Project)