JavaScript最全编码规范
轉載: JavaScript最全編碼規范
類型
●基本類型:訪問基本類型時,應該直接操作類型值
●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 對象
●使用字面量語法創建對象
// 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'
}; 數組
●使用字面量語法創建數組
// bad
var items = new Array();// good
var items = []; ●添加數組元素時,使用push而不是直接添加
var someStack = [];// bad
someStack[someStack.length] = 'abracadabra';// good
someStack.push('abracadabra'); ●需要復制數組時,可以使用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(); ●使用slice將類數組對象轉為數組
function trigger() {
var args = Array.prototype.slice.call(arguments);
...
} 字符串
●對字符串使用單引號
// bad
var name = "Bob Parr";// good
var name = 'Bob Parr';// bad
var fullName = "Bob " + this.lastName;// good
var fullName = 'Bob ' + this.lastName; ●超過80個字符的字符串應該使用字符串連接符進行跨行
●注意:對長字符串過度使用連接符將會影響性能。相關的文章和主題討論: jsPerf & Discussion.
// 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方法而不是通過連接符,尤其是在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;// 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] = '<li>' + messages[i].message + '</li>';
}return '<ul>' + items.join('') + '</ul>';
} 函數
●函數表達式
// 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.');
})(); ●不要在非函數塊中(if, while, etc)聲明函數,盡管瀏覽器允許你分配函數給一個變量,但壞消息是,不同的瀏覽器用不同的方式解析它
●注意:ECMA-262把塊定義為一組語句,但函數聲明不是一個語句: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,否則它將優先于傳遞給每個函數作用域中的arguments對象,
// bad
function nope(name, options, arguments) {
// ...stuff...
}// good
function yup(name, options, args) {
// ...stuff...
} 屬性
●使用點表示法訪問屬性
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'); 變量
●總是使用var聲明變量,不然其將變為全局變量。我們要想辦法避免全局空間污染
// bad
superPower = new SuperPower();// good
var superPower = new SuperPower(); ●使用var聲明每個變量,這樣很容易添加新的變量聲明,而不用去擔心用a;替換a,
// bad
var items = getItems(),
goSportsTeam = true,
dragonball = 'z';// bad
// (compare to above, and try to spot the mistake)
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;
}return true;
}// good
function() {
if (!arguments.length) {
return false;
}var name = getName();return true;
} 聲明提升
●變量聲明是在作用域的頂端,但是賦值沒有
// we know this wouldn't work (assuming there
// is no notDefined global variable)
function example() {
console.log(notDefined); // => throws a ReferenceError
}// creating a variable declaration after you
// reference the variable will work due to
// variable hoisting. Note: the assignment
// value of `true` is not hoisted.
function example() {
console.log(declaredButNotAssigned); // => undefined
var declaredButNotAssigned = true;
}// The interpreter is hoisting the variable
// declaration to the top of the scope,
// which means our example could be rewritten as:
function example() {
var declaredButNotAssigned;
console.log(declaredButNotAssigned); // => undefined
declaredButNotAssigned = true;
} ●匿名表達式能提升他們的變量名,但不能提升函數賦值
function example() {
console.log(anonymous); // => undefinedanonymous(); // => TypeError anonymous is not a functionvar anonymous = function() {
console.log('anonymous function expression');
};
} ●命名函數表達式會提升變量名,而不是函數名或者函數體
function example() {
console.log(named); // => undefinednamed(); // => TypeError named is not a functionsuperPower(); // => ReferenceError superPower is not definedvar 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); // => undefinednamed(); // => TypeError named is not a functionvar named = function named() {
console.log('named');
}
} ●函數聲明會提升變量名和函數體
function example() {
superPower(); // => Flyingfunction superPower() {
console.log('Flying');
}
} 更多信息指引:JavaScript Scoping & Hoisting by Ben Cherry.
比較運算符&相等
●使用===和!==代替==和!=
●比較運算符進行計算時會利用ToBoolean方法進行強制轉換數據類型,并遵從一下規則
●Objects的計算值是true
●Undefined的計算值是false
●Boolean的計算值是boolean的值
●Numbers如果是-0,+0或者NaN,則計算值是false,反之是true
●Strings如果是空,則計算值是false,反之是true
if ([0]) {
// true
// An array is an object, objects evaluate to true
} ●使用快捷方式
// bad
if (name !== '') {
// ...stuff...
}// good
if (name) {
// ...stuff...
}// bad
if (collection.length > 0) {
// ...stuff...
}// good
if (collection.length) {
// ...stuff...
} 語句塊
●對多行的語句塊使用大括號
// bad
if (test)
return false;// good
if (test) return false;// good
if (test) {
return false;
}// bad
function() { return false; }// good
function() {
return false;
} ●對于使用if和else的多行語句塊,把else和if語句塊的右大括號放在同一行
// bad
if (test) {
thing1();
thing2();
}
else {
thing3();
}// good
if (test) {
thing1();
thing2();
} else {
thing3();
} 注釋
●多行注釋使用/** … */,需包含一個描述、所有參數的具體類型和值以及返回值
// 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 or TODO 前綴有利于其他開發者快速理解。這些注釋不同于通常的注釋,因為它們是可實施的。這些實施措施就是FIXME -- need to figure this out or TODO -- need to implement.
●使用// 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;
} 空白
●使用軟制表符設置兩個空格
// bad
function() {
????var name;
}// bad
function() {
?var name;
}// good
function() {
??var name;
} ●在左大括號之前留一個空格
// bad
function test(){
console.log('test');
}// good
function test() {
console.log('test');
}// bad
dog.set('attr',{
age: '1 year',
breed: 'Bernese Mountain Dog'
});// good
dog.set('attr', {
age: '1 year',
breed: 'Bernese Mountain Dog'
}); ●在控制語句中(if, while etc),左括號之前留一個空格。函數的參數列表之前不要有空格
// bad
if(isJedi) {
fight ();
}// good
if (isJedi) {
fight();
}// bad
function fight () {
console.log ('Swooosh!');
}// good
function fight() {
console.log('Swooosh!');
} ●用空白分隔運算符
// bad
var x=y+5;// good
var x = y + 5; ●用一個換行符結束文件
// bad
(function(global) {
// ...stuff...
})(this);
// bad
(function(global) {
// ...stuff...
})(this);?
?
// good
(function(global) {
// ...stuff...
})(this);? ●當調用很長的方法鏈時使用縮進,可以強調這行是方法調用,不是新的語句
// bad
$('#items').find('.selected').highlight().end().find('.open').updateCount();// bad
$('#items').
find('.selected').
highlight().
end().
find('.open').
updateCount();// good
$('#items')
.find('.selected')
.highlight()
.end()
.find('.open')
.updateCount();// bad
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);// good
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); ●在語句塊和下一個語句之前留一個空行
// bad
if (foo) {
return bar;
}
return baz;// good
if (foo) {
return bar;
}return baz;// bad
var obj = {
foo: function() {
},
bar: function() {
}
};
return obj;// good
var obj = {
foo: function() {
},bar: function() {
}
};return obj; 逗號
●不要在語句前留逗號
// bad
var story = [
once
, upon
, aTime
];// good
var story = [
once,
upon,
aTime
];// bad
var hero = {
firstName: 'Bob'
, lastName: 'Parr'
, heroName: 'Mr. Incredible'
, superPower: 'strength'
};// good
var hero = {
firstName: 'Bob',
lastName: 'Parr',
heroName: 'Mr. Incredible',
superPower: 'strength'
}; ●不要有多余逗號:這會在IE6、IE7和IE9的怪異模式中導致一些問題;同時,在ES3的一些實現中,多余的逗號會增加數組的長度。在ES5中已經澄清(source)
// bad
var hero = {
firstName: 'Kevin',
lastName: 'Flynn',
};var heroes = [
'Batman',
'Superman',
];// good
var hero = {
firstName: 'Kevin',
lastName: 'Flynn'
};var heroes = [
'Batman',
'Superman'
]; 分號
●恩,這也是規范一部分
// bad
(function() {
var name = 'Skywalker'
return name
})()// good
(function() {
var name = 'Skywalker';
return name;
})();// good (guards against the function becoming an argument when two files with IIFEs are concatenated)
;(function() {
var name = 'Skywalker';
return name;
})(); 類型分配&強制轉換
●執行強制類型轉換的語句。
●Strings:
// => 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對Numbers進行轉換,并帶一個進制作為參數
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); ●無論出于什么原因,或許你做了一些”粗野”的事;或許parseInt成了你的瓶頸;或許考慮到性能,需要使用位運算,都要用注釋說明你為什么這么做
// good
/**
* parseInt was the reason my code was slow.
* Bitshifting the String to coerce it to a
* Number made it a lot faster.
*/
var val = inputValue >> 0; ●注意:當使用位運算時,Numbers被視為64位值,但是位運算總是返回32位整型(source)。對于整型值大于32位的進行位運算將導致不可預見的行為。Discussion.最大的有符號32位整數是2,147,483,647
2147483647 >> 0 //=> 2147483647
2147483648 >> 0 //=> -2147483648
2147483649 >> 0 //=> -2147483647 ●Booleans:
var age = 0;// bad
var hasAge = new Boolean(age);// good
var hasAge = Boolean(age);// good
var hasAge = !!age; 命名規范
●避免單字母名稱,讓名稱具有描述性
// bad
function q() {
// ...stuff...
}// good
function query() {
// ..stuff..
} ●當命名對象、函數和實例時使用駱駝拼寫法
// bad
var OBJEcttsssss = {};
var this_is_my_object = {};
function c() {}
var u = new user({
name: 'Bob Parr'
});// good
var thisIsMyObject = {};
function thisIsMyFunction() {}
var user = new User({
name: 'Bob Parr'
}); ●當命名構造函數或類名時,使用駝峰式寫法
// bad
function user(options) {
this.name = options.name;
}var bad = new user({
name: 'nope'
});// good
function User(options) {
this.name = options.name;
}var good = new User({
name: 'yup'
}); ●命名私有屬性時使用前置下劃線
// bad
this.__firstName__ = 'Panda';
this.firstName_ = 'Panda';// good
this._firstName = 'Panda'; ●保存this引用時使用_this
// bad
function() {
var self = this;
return function() {
console.log(self);
};
}// bad
function() {
var that = this;
return function() {
console.log(that);
};
}// good
function() {
var _this = this;
return function() {
console.log(_this);
};
} ●命名函數時,下面的方式有利于堆棧跟蹤
// bad
var log = function(msg) {
console.log(msg);
};// good
var log = function log(msg) {
console.log(msg);
}; ●注意:IE8和怪異模式下命名函數表示,戳此:http://kangax.github.io/nfe/
●如果文件作為一個類被導出,文件名應該和類名保持一致
// file contents
class CheckBox {
// ...
}
module.exports = CheckBox;// in some other file
// bad
var CheckBox = require('./checkBox');// bad
var CheckBox = require('./check_box');// good
var CheckBox = require('./CheckBox'); 存取器
●對于屬性,訪問器函數不是必須的
●如果定義了存取器函數,應參照getVal() 和 setVal(‘hello’)格式.
// bad
dragon.age();// good
dragon.getAge();// bad
dragon.age(25);// good
dragon.setAge(25); ●如果屬性時boolean,格式應為isVal() or hasVal().
// bad
if (!dragon.age()) {
return false;
}// good
if (!dragon.hasAge()) {
return false;
} ●創建get() and set()函數時不錯的想法,但是要保持一致
function Jedi(options) {
options || (options = {});
var lightsaber = options.lightsaber || 'blue';
this.set('lightsaber', lightsaber);
}Jedi.prototype.set = function(key, val) {
this[key] = val;
};Jedi.prototype.get = function(key) {
return this[key];
}; 構造函數
●在原型對象上定義方法,而不是用新對象重寫它。重寫使繼承變為不可能:重置原型將重寫整個基類
function Jedi() {
console.log('new jedi');
}// bad
Jedi.prototype = {
fight: function fight() {
console.log('fighting');
},block: function block() {
console.log('blocking');
}
};// good
Jedi.prototype.fight = function fight() {
console.log('fighting');
};Jedi.prototype.block = function block() {
console.log('blocking');
}; ●方法應該返回this,有利于構成方法鏈
// bad
Jedi.prototype.jump = function() {
this.jumping = true;
return true;
};Jedi.prototype.setHeight = function(height) {
this.height = height;
};var luke = new Jedi();
luke.jump(); // => true
luke.setHeight(20); // => undefined// good
Jedi.prototype.jump = function() {
this.jumping = true;
return this;
};Jedi.prototype.setHeight = function(height) {
this.height = height;
return this;
};var luke = new Jedi();luke.jump()
.setHeight(20); ●寫一個自定義的toString()方法是可以的,只要確保它能正常運行并且不會產生副作用
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();
}; 事件
●當在事件對象上附加數據時(無論是DOM事件還是如Backbone一樣擁有的私有事件),應傳遞散列對象而不是原始值,這可以讓隨后的貢獻者給事件對象添加更多的數據,而不必去查找或者更新每一個事件處理程序。舉個粟子,不要用下面的方式:
// 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
}); 模塊
●模塊應該以 ! 開始,這能確保當腳本連接時,如果畸形模塊忘記導入,包括最后一個分號,不會產生錯誤。Explanation
●文件應該以駝峰式命名,放在同名的文件夾中,和單出口的名稱相匹配
●定義一個noConflict()方法來設置導出模塊之前的版本,并返回當前版本。
●在模塊的頂部申明’use strict';
// fancyInput/fancyInput.js!function(global) {
'use strict';var previousFancyInput = global.FancyInput;function FancyInput(options) {
this.options = options || {};
}FancyInput.noConflict = function noConflict() {
global.FancyInput = previousFancyInput;
return FancyInput;
};global.FancyInput = FancyInput;
}(this); jQuery
●jQuery對象變量使用前綴$
// bad
var sidebar = $('.sidebar');// good
var $sidebar = $('.sidebar'); ●緩存jQuery查詢
// bad
function setSidebar() {
$('.sidebar').hide();// ...stuff...$('.sidebar').css({
'background-color': 'pink'
});
}// good
function setSidebar() {
var $sidebar = $('.sidebar');
$sidebar.hide();// ...stuff...$sidebar.css({
'background-color': 'pink'
});
} ●使用級聯\((‘.sidebar ul’)或父子\)(‘.sidebar > ul’)選擇器進行DOM查詢。jsPerf
●在范圍內使用find進行jQuery對象查詢
// bad
$('ul', '.sidebar').hide();// bad
$('.sidebar').find('ul').hide();// good
$('.sidebar ul').hide();// good
$('.sidebar > ul').hide();// good
$sidebar.find('ul').hide();
轉載于:https://www.cnblogs.com/andy-zhou/p/5306925.html
總結
以上是生活随笔為你收集整理的JavaScript最全编码规范的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 泪的告白是谁唱的啊?
- 下一篇: “感此因念彼”下一句是什么