Title here
" + "This is a paragraph
" + "" + "摘要:示例空格強(qiáng)制二元運(yùn)算符兩側(cè)必須有一個(gè)空格,一元運(yùn)算符與操作對(duì)象之間不允許有空格。示例強(qiáng)制行尾不得有多余的空格。示例建議函數(shù)聲明具名函數(shù)表達(dá)式函數(shù)調(diào)用中,函數(shù)名和之間不允許有空格。示例命名強(qiáng)制變量使用命名法。
1. 代碼風(fēng)格 1.1 文件 [強(qiáng)制] JavaScript 文件使用無 BOM 的 UTF-8 編碼。 [建議] 在文件結(jié)尾處,保留一個(gè)空行。 1.2 結(jié)構(gòu) 1.2.1 縮進(jìn) [強(qiáng)制] 使用 4 個(gè)空格做為一個(gè)縮進(jìn)層級(jí),不允許使用 2 個(gè)空格 或 tab 字符。 [強(qiáng)制] switch 下的 case 和 default 必須增加一個(gè)縮進(jìn)層級(jí)。這段時(shí)間在整理前端代碼規(guī)范,現(xiàn)將JS部分的內(nèi)容整理,都是基本基礎(chǔ)的內(nèi)容。請(qǐng)各位大神斧正!!
目前已經(jīng)整理如下的代碼規(guī)范:HTML編碼規(guī)范 、 CSSS編碼規(guī)范 、 CSS規(guī)范--BEM入門
示例:
// good switch (variable) { case "1": // do... break; case "2": // do... break; default: // do... } ------------ // bad switch (variable) { case "1": // do... break; case "2": // do... break; default: // do... }1.2.2空格 [強(qiáng)制] 二元運(yùn)算符兩側(cè)必須有一個(gè)空格,一元運(yùn)算符與操作對(duì)象之間不允許有空格。
示例:
var a = !arr.length; a++; a = b + c;[強(qiáng)制] 在對(duì)象創(chuàng)建時(shí),屬性中的 : 之后必須有空格, : 之前不允許有空格。
示例:
// good var obj = { a: 1, b: 2, c: 3 }; ------------ // bad var obj = { a : 1, b:2, c :3 };[強(qiáng)制] , 和 ; 前不允許有空格。如果不位于行尾, 和 ; 后必須跟一個(gè)空格。
示例:
// good callFunc(a, b); ------------ // bad callFunc(a , b) ;[強(qiáng)制] 單行聲明的數(shù)組與對(duì)象,如果包含元素, {} 和 [] 內(nèi)緊貼括號(hào)部分不允許包含空格。
示例:
解釋:
聲明包含元素的數(shù)組與對(duì)象,只有當(dāng)內(nèi)部元素的形式較為簡單時(shí),才允許寫在一行。元素復(fù)雜的情況,還是應(yīng)該換行書寫。
示例:
// good var arr1 = []; var arr2 = [1, 2, 3]; var obj1 = {}; var obj2 = {name: "obj"}; var obj3 = { name: "obj", age: 20, sex: 1 }; ------------ // bad var arr1 = [ ]; var arr2 = [ 1, 2, 3 ]; var obj1 = { }; var obj2 = { name: "obj" }; var obj3 = {name: "obj", age: 20, sex: 1};[強(qiáng)制] 行尾不得有多余的空格。 [建議] 用作代碼塊起始的左花括號(hào){前必須有一個(gè)空格。
示例:
// good if (condition) { } while (condition) { } function funcName() { } ------------ // bad if (condition){ } while (condition){ } function funcName(){ }[建議] if / else / for / while / function / switch / do / try / catch / finally 關(guān)鍵字后,必須有一個(gè)空格。
示例:
// good if (condition) { } while (condition) { } (function () { })(); ------------ // bad if(condition) { } while(condition) { } (function() { })();[建議] 函數(shù)聲明、具名函數(shù)表達(dá)式、函數(shù)調(diào)用中,函數(shù)名和(之間不允許有空格。
示例:
// good function funcName() { } var funcName = function funcName() { }; funcName(); ------------ // bad function funcName () { } var funcName = function funcName () { }; funcName ();1.2.3換行 [強(qiáng)制] 每個(gè)獨(dú)立語句結(jié)束后必須換行。 [強(qiáng)制] 每行不得超過 120 個(gè)字符。
解釋:
超長的不可分割的代碼允許例外,比如復(fù)雜的正則表達(dá)式。長字符串不在例外之列。
示例:
// good if (user.isAuthenticated() && user.isInRole("admin") && user.hasAuthority("add-admin") || user.hasAuthority("delete-admin") ) { // Code } var result = number1 + number2 + number3 + number4 + number5; ------------ // bad if (user.isAuthenticated() && user.isInRole("admin") && user.hasAuthority("add-admin") || user.hasAuthority("delete-admin")) { // Code } var result = number1 + number2 + number3 + number4 + number5;[強(qiáng)制] 在函數(shù)聲明、函數(shù)表達(dá)式、函數(shù)調(diào)用、對(duì)象創(chuàng)建、數(shù)組創(chuàng)建、for 語句等場景中,不允許在 , 或 ; 前換行。
示例:
// good var obj = { a: 1, b: 2, c: 3 }; foo( aVeryVeryLongArgument, anotherVeryLongArgument, callback ); ------------ // bad var obj = { a: 1 , b: 2 , c: 3 }; foo( aVeryVeryLongArgument , anotherVeryLongArgument , callback );[建議] 不同行為或邏輯的語句集,使用空行隔開,更易閱讀。
示例:
// 僅為按邏輯換行的示例,不代表setStyle的最優(yōu)實(shí)現(xiàn) function setStyle(element, property, value) { if (element == null) { return; } element.style[property] = value; }[建議] 在語句的行長度超過 120 時(shí),根據(jù)邏輯條件合理縮進(jìn)。
示例:
// 較復(fù)雜的邏輯條件組合,將每個(gè)條件獨(dú)立一行,邏輯運(yùn)算符放置在行首進(jìn)行分隔,或?qū)⒉糠诌壿嫲催壿嫿M合進(jìn)行分隔。 // 建議最終將右括號(hào) ) 與左大括號(hào) { 放在獨(dú)立一行,保證與 `if` 內(nèi)語句塊能容易視覺辨識(shí)。 if (user.isAuthenticated() && user.isInRole("admin") && user.hasAuthority("add-admin") || user.hasAuthority("delete-admin") ) { // Code } // 按一定長度截?cái)嘧址?,并使?+ 運(yùn)算符進(jìn)行連接。 // 分隔字符串盡量按語義進(jìn)行,如不要在一個(gè)完整的名詞中間斷開。 // 特別的,對(duì)于 HTML 片段的拼接,通過縮進(jìn),保持和 HTML 相同的結(jié)構(gòu)。 var html = "" // 此處用一個(gè)空字符串,以便整個(gè) HTML 片段都在新行嚴(yán)格對(duì)齊 + "[建議] 對(duì)于 if...else...、try...catch...finally 等語句,推薦使用在 } 號(hào)后添加一個(gè)換行 的風(fēng)格,使代碼層次結(jié)構(gòu)更清晰,閱讀性更好。" + " "; // 也可使用數(shù)組來進(jìn)行拼接,相對(duì) `+` 更容易調(diào)整縮進(jìn)。 var html = [ "Title here
" + "This is a paragraph
" + "" + "", " " ]; html = html.join(""); // 當(dāng)參數(shù)過多時(shí),將每個(gè)參數(shù)獨(dú)立寫在一行上,并將結(jié)束的右括號(hào) ) 獨(dú)立一行。 // 所有參數(shù)必須增加一個(gè)縮進(jìn)。 foo( aVeryVeryLongArgument, anotherVeryLongArgument, callback ); // 也可以按邏輯對(duì)參數(shù)進(jìn)行組合。 // 最經(jīng)典的是 baidu.format 函數(shù),調(diào)用時(shí)將參數(shù)分為“模板”和“數(shù)據(jù)”兩塊 baidu.format( dateFormatTemplate, year, month, date, hour, minute, second ); // 當(dāng)函數(shù)調(diào)用時(shí),如果有一個(gè)或以上參數(shù)跨越多行,應(yīng)當(dāng)每一個(gè)參數(shù)獨(dú)立一行。 // 這通常出現(xiàn)在匿名函數(shù)或者對(duì)象初始化等作為參數(shù)時(shí),如 `setTimeout` 函數(shù)等。 setTimeout( function () { alert("hello"); }, 200 ); order.data.read( "id=" + me.model.id, function (data) { me.attchToModel(data.result); callback(); }, 300 ); // 鏈?zhǔn)秸{(diào)用較長時(shí)采用縮進(jìn)進(jìn)行調(diào)整。 $("#items") .find(".selected") .highlight() .end(); // 三元運(yùn)算符由3部分組成,因此其換行應(yīng)當(dāng)根據(jù)每個(gè)部分的長度不同,形成不同的情況。 var result = thisIsAVeryVeryLongCondition ? resultA : resultB; var result = condition ? thisIsAVeryVeryLongResult : resultB; // 數(shù)組和對(duì)象初始化的混用,嚴(yán)格按照每個(gè)對(duì)象的 `{` 和結(jié)束 `}` 在獨(dú)立一行的風(fēng)格書寫。 var array = [ { // ... }, { // ... } ];Title here
", "This is a paragraph
", "", "
示例:
if (condition) { // some statements; } else { // some statements; } try { // some statements; } catch (ex) { // some statements; }1.2.4語句 [強(qiáng)制] 不得省略語句結(jié)束的分號(hào)。 [強(qiáng)制] 在 if / else / for / do / while 語句中,即使只有一行,也不得省略塊 {...}。
示例:
// good if (condition) { callFunc(); } ------------ // bad if (condition) callFunc(); if (condition) callFunc();
示例:
// good function funcName() { } ------------ // bad function funcName() { }; // 如果是函數(shù)表達(dá)式,分號(hào)是不允許省略的。 var funcName = function () { };[強(qiáng)制] IIFE 必須在函數(shù)表達(dá)式外添加 (,非 IIFE 不得在函數(shù)表達(dá)式外添加 (。
解釋:
IIFE = Immediately-Invoked Function Expression.
額外的 ( 能夠讓代碼在閱讀的一開始就能判斷函數(shù)是否立即被調(diào)用,進(jìn)而明白接下來代碼的用途。而不是一直拖到底部才恍然大悟。
示例:
// good var task = (function () { // Code return result; })(); var func = function () { }; ------------ // bad var task = function () { // Code return result; }(); var func = (function () { });1.3命名 [強(qiáng)制] 變量 使用 Camel命名法。
示例:
var loadingModules = {};[強(qiáng)制] jQuery對(duì)象變量,使用$作為變量名前綴。
示例:
// good var $sidebar = $(".sidebar"); ------------ // bad var sidebar = $(".sidebar");[強(qiáng)制] 常量 使用 全部字母大寫,單詞間下劃線分隔 的命名方式。
示例:
var HTML_ENTITY = {};[強(qiáng)制] 函數(shù) 使用 Camel命名法。
示例:
function getStyle(element) { }[建議] 函數(shù)名 使用 動(dòng)賓短語。
示例:
function getStyle(element) { }[強(qiáng)制] 類 使用 Pascal命名法。
示例:
function TextNode(options) { }[強(qiáng)制] 類名 使用 名詞。
示例:
function Engine(options) { }[強(qiáng)制] 類的 方法 / 屬性 使用 Camel命名法。
示例:
function TextNode(value, engine) { this.value = value; this.engine = engine; } TextNode.prototype.clone = function () { return this; };[強(qiáng)制] 枚舉變量 使用 Pascal命名法,枚舉的屬性 使用 全部字母大寫,單詞間下劃線分隔 的命名方式。
示例:
var TargetState = { READING: 1, READED: 2, APPLIED: 3, READY: 4 };[強(qiáng)制] 由多個(gè)單詞組成的縮寫詞,在命名中,根據(jù)當(dāng)前命名法和出現(xiàn)的位置,所有字母的大小寫與首字母的大小寫保持一致。
示例:
function XMLParser() { } function insertHTML(element, html) { } var httpRequest = new HTTPRequest();[建議] boolean 類型的變量使用 is 或 has 開頭。
示例:
var isReady = false; var hasMoreCommands = false;[建議] Promise對(duì)象 用 動(dòng)賓短語的進(jìn)行時(shí) 表達(dá)。
示例:
var loadingData = ajax.get("url"); loadingData.then(callback);[建議] 不保存this引用,使用Function#bind。
示例:
// good function () { return function () { console.log(this); }.bind(this); } // bad function () { var self = this; return function () { console.log(self); }; } // bad function () { var that = this; return function () { console.log(that); }; } // bad function () { var _this = this; return function () { console.log(_this); }; }1.4 注釋 1.4.1 單行注釋 [強(qiáng)制] 必須獨(dú)占一行。// 后跟一個(gè)空格,縮進(jìn)與下一行被注釋說明的代碼一致。 1.4.2多行注釋 [建議] 避免使用 /.../ 這樣的多行注釋。有多行注釋內(nèi)容時(shí),使用多個(gè)單行注釋。 1.4.3文檔化注釋 [強(qiáng)制] 為了便于代碼閱讀和自文檔化,以下內(nèi)容必須包含以 /*.../ 形式的塊注釋中。
解釋:
文件
namespace
類
函數(shù)或方法
類屬性
事件
全局變量
常量
[強(qiáng)制] 文檔注釋前必須空一行。 [建議] 自文檔化的文檔說明 what,而不是 how。 1.4.4類型定義 [強(qiáng)制] 類型定義都是以 { 開始, 以 } 結(jié)束。解釋:
常用類型如:{string}, {number}, {boolean}, {Object}, {Function}, {RegExp}, {Array}, {Date}。
類型不僅局限于內(nèi)置的類型,也可以是自定義的類型。比如定義了一個(gè)類 Developer,就可以使用它來定義一個(gè)參數(shù)和返回值的類型。
示例:
示例:
/** * @file Describe the file */1.4.6 類注釋 [強(qiáng)制] 類的屬性或方法等成員信息不是 public 的,應(yīng)使用 @protected 或 @private 標(biāo)識(shí)可訪問性。
解釋:
生成的文檔中將有可訪問性的標(biāo)記,避免用戶直接使用非 public 的屬性或方法。
示例:
/** * 類描述 * * @class * @extends Developer */ var Fronteer = function () { Developer.call(this); /** * 屬性描述 * * @type {string} * @private */ this.level = "T12"; // constructor body }; util.inherits(Fronteer, Developer); /** * 方法描述 * * @private * @return {string} 返回值描述 */ Fronteer.prototype.getLevel = function () { };[建議] 使用 @class 標(biāo)記類或構(gòu)造函數(shù)。
示例:
/** * 描述 * * @class */ function Developer() { // constructor body }[建議] 使用 @extends 標(biāo)記類的繼承信息。
示例:
/** * 描述 * * @class * @extends Developer */ function Fronteer() { Developer.call(this); // constructor body } util.inherits(Fronteer, Developer);1.4.7 函數(shù)/方法注釋 [強(qiáng)制] 函數(shù)/方法注釋必須包含函數(shù)說明,有參數(shù)和返回值時(shí)必須使用注釋標(biāo)識(shí)。
解釋:
當(dāng) return 關(guān)鍵字僅作退出函數(shù)/方法使用時(shí),無須對(duì)返回值作注釋標(biāo)識(shí)。
示例:
/** * 函數(shù)描述 * * @param {string} p1 參數(shù)1的說明 * @param {string} p2 參數(shù)2的說明,比較長 * 那就換行了. * @param {number=} p3 參數(shù)3的說明(可選) * @return {Object} 返回值描述 */ function foo(p1, p2, p3) { var p3 = p3 || 10; return { p1: p1, p2: p2, p3: p3 }; }[強(qiáng)制] 對(duì) Object 中各項(xiàng)的描述, 必須使用 @param 標(biāo)識(shí)。
示例:
/** * 函數(shù)描述 * * @param {Object} option 參數(shù)描述 * @param {string} option.url option項(xiàng)描述 * @param {string=} option.method option項(xiàng)描述,可選參數(shù) */ function foo(option) { // TODO }1.4.8 事件注釋 [強(qiáng)制] 必須使用 @event 標(biāo)識(shí)事件,事件參數(shù)的標(biāo)識(shí)與方法描述的參數(shù)標(biāo)識(shí)相同。
示例:
/** * 值變更時(shí)觸發(fā) * * @event Select#change * @param {Object} e e描述 * @param {string} e.before before描述 * @param {string} e.after after描述 */ this.fire( "change", { before: "foo", after: "bar" } );[建議] 對(duì)于事件對(duì)象的注釋,使用 @param 標(biāo)識(shí),生成文檔時(shí)可讀性更好。
示例:
/** * 點(diǎn)擊處理 * * @fires Select#change * @private */ Select.prototype.clickHandler = function () { /** * 值變更時(shí)觸發(fā) * * @event Select#change * @param {Object} e e描述 * @param {string} e.before before描述 * @param {string} e.after after描述 */ this.fire( "change", { before: "foo", after: "bar" } ); };1.4.9 常量注釋 [強(qiáng)制] 常量必須使用 @const 標(biāo)記,并包含說明和類型信息。
示例:
/** * 常量說明 * * @const * @type {string} */ var REQUEST_URL = "myurl.do";1.4.10 細(xì)節(jié)注釋 [強(qiáng)制] 有時(shí)我們會(huì)使用一些特殊標(biāo)記進(jìn)行說明。特殊標(biāo)記必須使用單行注釋的形式。下面列舉了一些常用標(biāo)記:
解釋:
TODO: 有功能待實(shí)現(xiàn)。此時(shí)需要對(duì)將要實(shí)現(xiàn)的功能進(jìn)行簡單說明。
FIXME: 該處代碼運(yùn)行沒問題,但可能由于時(shí)間趕或者其他原因,需要修正。此時(shí)需要對(duì)如何修正進(jìn)行簡單說明。
HACK: 為修正某些問題而寫的不太好或者使用了某些詭異手段的代碼。此時(shí)需要對(duì)思路或詭異手段進(jìn)行描述。
XXX: 該處存在陷阱。此時(shí)需要對(duì)陷阱進(jìn)行描述。
2. 語言特性 2.1 變量 [強(qiáng)制] 變量、函數(shù)在使用前必須先定義。解釋:
不通過 var 定義變量將導(dǎo)致變量污染全局環(huán)境。
示例:
// good var name = "MyName"; ------------ // bad name = "MyName";
原則上不建議使用全局變量,對(duì)于已有的全局變量或第三方框架引入的全局變量,需要根據(jù)檢查工具的語法標(biāo)識(shí)。
示例:
/* globals jQuery */ var element = jQuery("#element-id");
[建議] 最后再聲明未賦值的變量。當(dāng)你需要引用前面的變量賦值時(shí)這將變的很有用。
示例:
// good var items = getItems(); var goSportsTeam = true; var dragonball; var length; var i; ------------ // bad var i, len, dragonball, items = getItems(), goSportsTeam = true; // bad var i; var items = getItems(); var dragonball; var goSportsTeam = true; var len;[強(qiáng)制] 變量必須 即用即聲明,不得在函數(shù)或其它形式的代碼塊起始位置統(tǒng)一聲明所有變量。
解釋:
變量聲明與使用的距離越遠(yuǎn),出現(xiàn)的跨度越大,代碼的閱讀與維護(hù)成本越高。雖然JavaScript的變量是函數(shù)作用域,還是應(yīng)該根據(jù)編程中的意圖,縮小變量出現(xiàn)的距離空間。
示例:
// good function kv2List(source) { var list = []; for (var key in source) { if (source.hasOwnProperty(key)) { var item = { k: key, v: source[key] }; list.push(item); } } return list; } ------------ // bad function kv2List(source) { var list = []; var key; var item; for (key in source) { if (source.hasOwnProperty(key)) { item = { k: key, v: source[key] }; list.push(item); } } return list; }2.2條件 [強(qiáng)制] 在 Equality Expression 中使用類型嚴(yán)格的 ===。僅當(dāng)判斷 null 或 undefined 時(shí),允許使用 == null。
解釋:
使用 === 可以避免等于判斷中隱式的類型轉(zhuǎn)換。
示例:
// good if (age === 30) { // ...... } ------------ // bad if (age == 30) { // ...... }[建議] 盡可能使用簡潔的表達(dá)式。
示例:
// 字符串為空 // good if (!name) { // ...... } ------------ // bad if (name === "") { // ...... }
// 字符串非空 // good if (name) { // ...... } ------------ // bad if (name !== "") { // ...... }
// 數(shù)組非空 // good if (collection.length) { // ...... } ------------ // bad if (collection.length > 0) { // ...... }
// 布爾不成立 // good if (!notTrue) { // ...... } ------------ // bad if (notTrue === false) { // ...... }
// null 或 undefined // good if (noValue == null) { // ...... } ------------ // bad if (noValue === null || typeof noValue === "undefined") { // ...... }[建議] 按執(zhí)行頻率排列分支的順序。
解釋:
按執(zhí)行頻率排列分支的順序好處是:
閱讀的人容易找到最常見的情況,增加可讀性。
提高執(zhí)行效率。
[建議] 對(duì)于相同變量或表達(dá)式的多值條件,用 switch 代替 if。示例:
// good switch (typeof variable) { case "object": // ...... break; case "number": case "boolean": case "string": // ...... break; } ------------ // bad var type = typeof variable; if (type === "object") { // ...... } else if (type === "number" || type === "boolean" || type === "string") { // ...... }2.3循環(huán) [建議] 不要在循環(huán)體中包含函數(shù)表達(dá)式,事先將函數(shù)提取到循環(huán)體外。
解釋:
循環(huán)體中的函數(shù)表達(dá)式,運(yùn)行過程中會(huì)生成循環(huán)次數(shù)個(gè)函數(shù)對(duì)象。
示例:
// good function clicker() { // ...... } for (var i = 0, len = elements.length; i < len; i++) { var element = elements[i]; addListener(element, "click", clicker); } // bad for (var i = 0, len = elements.length; i < len; i++) { var element = elements[i]; addListener(element, "click", function () {}); }[建議] 對(duì)循環(huán)內(nèi)多次使用的不變值,在循環(huán)外用變量緩存。
示例:
// good var width = wrap.offsetWidth + "px"; for (var i = 0, len = elements.length; i < len; i++) { var element = elements[i]; element.style.width = width; // ...... } // bad for (var i = 0, len = elements.length; i < len; i++) { var element = elements[i]; element.style.width = wrap.offsetWidth + "px"; // ...... }[建議] 對(duì)有序集合進(jìn)行遍歷時(shí),緩存 length。
解釋:
雖然現(xiàn)代瀏覽器都對(duì)數(shù)組長度進(jìn)行了緩存,但對(duì)于一些宿主對(duì)象和老舊瀏覽器的數(shù)組對(duì)象,在每次 length 訪問時(shí)會(huì)動(dòng)態(tài)計(jì)算元素個(gè)數(shù),此時(shí)緩存 length 能有效提高程序性能。
示例:
for (var i = 0, len = elements.length; i < len; i++) { var element = elements[i]; // ...... }[建議] 對(duì)有序集合進(jìn)行順序無關(guān)的遍歷時(shí),使用逆序遍歷。
解釋:
逆序遍歷可以節(jié)省變量,代碼比較優(yōu)化。
示例:
var len = elements.length; while (len--) { var element = elements[len]; // ...... }2.4 類型 2.4.1類型檢測 [建議] 類型檢測優(yōu)先使用 typeof。對(duì)象類型檢測使用 instanceof。null 或 undefined 的檢測使用 == null。
示例:
// string typeof variable === "string" // number typeof variable === "number" // boolean typeof variable === "boolean" // Function typeof variable === "function" // Object typeof variable === "object" // RegExp variable instanceof RegExp // Array variable instanceof Array // null variable === null // null or undefined variable == null // undefined typeof variable === "undefined"2.4.2類型轉(zhuǎn)換 [建議] 轉(zhuǎn)換成 string 時(shí),使用 + ""。
示例:
// good num + ""; // bad new String(num); num.toString(); String(num);[建議] 轉(zhuǎn)換成 number 時(shí),通常使用 +。
示例:
// good +str; // bad Number(str);[建議] string 轉(zhuǎn)換成 number,要轉(zhuǎn)換的字符串結(jié)尾包含非數(shù)字并期望忽略時(shí),使用 parseInt。
示例:
var width = "200px"; parseInt(width, 10);
示例:
// good parseInt(str, 10); // bad parseInt(str);[建議] 轉(zhuǎn)換成 boolean 時(shí),使用 !!。
示例:
var num = 3.14; !!num;[建議] number 去除小數(shù)點(diǎn),使用 Math.floor / Math.round / Math.ceil,不使用 parseInt。
示例:
// good var num = 3.14; Math.ceil(num); // bad var num = 3.14; parseInt(num, 10);2.5 字符串 [強(qiáng)制] 字符串開頭和結(jié)束使用單引號(hào) "。
解釋:
輸入單引號(hào)不需要按住 shift,方便輸入。
實(shí)際使用中,字符串經(jīng)常用來拼接 HTML。為方便 HTML 中包含雙引號(hào)而不需要轉(zhuǎn)義寫法。
示例:
var str = "我是一個(gè)字符串"; var html = "拼接HTML可以省去雙引號(hào)轉(zhuǎn)義";
[建議] 使用 數(shù)組 或 + 拼接字符串。
解釋:
使用 + 拼接字符串,如果拼接的全部是 StringLiteral,壓縮工具可以對(duì)其進(jìn)行自動(dòng)合并的優(yōu)化。所以,靜態(tài)字符串建議使用 + 拼接。
在現(xiàn)代瀏覽器下,使用 + 拼接字符串,性能較數(shù)組的方式要高。
如需要兼顧老舊瀏覽器,應(yīng)盡量使用數(shù)組拼接字符串。
示例:
// 使用數(shù)組拼接字符串 var str = [ // 推薦換行開始并縮進(jìn)開始第一個(gè)字符串, 對(duì)齊代碼, 方便閱讀. "
示例:
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; // good function inbox(messages) { items = []; for (i = 0; i < length; i++) { // use direct assignment in this case because we"re micro-optimizing. items[i] = "
解釋:
在 JavaScript 中拼接,并且最終將輸出到頁面中的字符串,需要進(jìn)行合理轉(zhuǎn)義,以防止安全漏洞。下面的示例代碼為場景說明,不能直接運(yùn)行。
示例:
// HTML 轉(zhuǎn)義 var str = "[建議] 復(fù)雜的數(shù)據(jù)到視圖字符串的轉(zhuǎn)換過程,選用一種模板引擎。" + htmlEncode(content) + "
"; // HTML 轉(zhuǎn)義 var str = ""; // URL 轉(zhuǎn)義 var str = "link"; // JavaScript字符串 轉(zhuǎn)義 + HTML 轉(zhuǎn)義 var str = "";
解釋:
使用模板引擎有如下好處:
在開發(fā)過程中專注于數(shù)據(jù),將視圖生成的過程由另外一個(gè)層級(jí)維護(hù),使程序邏輯結(jié)構(gòu)更清晰。
優(yōu)秀的模板引擎,通過模板編譯技術(shù)和高質(zhì)量的編譯產(chǎn)物,能獲得比手工拼接字符串更高的性能。
模板引擎能方便的對(duì)動(dòng)態(tài)數(shù)據(jù)進(jìn)行相應(yīng)的轉(zhuǎn)義,部分模板引擎默認(rèn)進(jìn)行HTML轉(zhuǎn)義,安全性更好。
介紹幾款模板插件:
artTemplate: 體積較小,在所有環(huán)境下性能高,語法靈活。
dot.js: 體積小,在現(xiàn)代瀏覽器下性能高,語法靈活。
etpl: 體積較小,在所有環(huán)境下性能高,模板復(fù)用性高,語法靈活。
handlebars: 體積大,在所有環(huán)境下性能高,擴(kuò)展性高。
hogon: 體積小,在現(xiàn)代瀏覽器下性能高。
nunjucks: 體積較大,性能一般,模板復(fù)用性高。
2.6 對(duì)象 [強(qiáng)制] 不允許修改和擴(kuò)展任何原生對(duì)象和宿主對(duì)象的原型。示例:
// 以下行為絕對(duì)禁止 String.prototype.trim = function () { };[建議] 使用對(duì)象字面量 {} 創(chuàng)建新 Object。
// good var obj = {}; // bad var obj = new Object();[建議] 對(duì)象創(chuàng)建時(shí),如果一個(gè)對(duì)象的所有 屬性 均可以不添加引號(hào),建議所有 屬性 不添加引號(hào)。如果任何一個(gè) 屬性 需要添加引號(hào),則所有 屬性 建議添加 "。
解釋:
如果屬性不符合 Identifier 和 NumberLiteral 的形式,就需要以 StringLiteral 的形式提供。
示例:
// good var info = { "name": "someone", "age": 28, "more-info": "..." }; // bad var info = { name: "someone", age: 28, "more-info": "..." };[建議] 屬性訪問時(shí),盡量使用 . 。
解釋:
屬性名符合 Identifier 的要求,就可以通過 . 來訪問,否則就只能通過 [expr] 方式訪問。
通常在 JavaScript 中聲明的對(duì)象,屬性命名是使用 Camel 命名法,用 . 來訪問更清晰簡潔。部分特殊的屬性(比如來自后端的 JSON ),可能采用不尋常的命名方式,可以通過 [expr] 方式訪問。
示例:
info.age; info["more-info"];[建議] for in 遍歷對(duì)象時(shí), 使用 hasOwnProperty 過濾掉原型中的屬性。
示例:
var newInfo = {}; for (var key in info) { if (info.hasOwnProperty(key)) { newInfo[key] = info[key]; } }2.7 數(shù)組 [建議] 使用數(shù)組字面量 [] 創(chuàng)建新數(shù)組,除非想要?jiǎng)?chuàng)建的是指定長度的數(shù)組。
示例:
// good var arr = []; // bad var arr = new Array();[強(qiáng)制] 遍歷數(shù)組不使用 for in。
解釋:
數(shù)組對(duì)象可能存在數(shù)字以外的屬性, 這種情況下 for in 不會(huì)得到正確結(jié)果。
示例:
var arr = ["a", "b", "c"]; // 這里僅作演示, 實(shí)際中應(yīng)使用 Object 類型 arr.other = "other things"; // 正確的遍歷方式 for (var i = 0, len = arr.length; i < len; i++) { console.log(i); } // 錯(cuò)誤的遍歷方式 for (var i in arr) { console.log(i); }[建議] 不因?yàn)樾阅艿脑蜃约簩?shí)現(xiàn)數(shù)組排序功能,盡量使用數(shù)組的 sort 方法。 [建議] 使用 Array#slice 將類數(shù)組對(duì)象轉(zhuǎn)換成數(shù)組。 [建議] 清空數(shù)組使用 .length = 0。 2.8 函數(shù) 2.8.1 函數(shù)長度 [建議] 一個(gè)函數(shù)的長度控制在 50 行以內(nèi)。
解釋:
將過多的邏輯單元混在一個(gè)大函數(shù)中,易導(dǎo)致難以維護(hù)。一個(gè)清晰易懂的函數(shù)應(yīng)該完成單一的邏輯單元。復(fù)雜的操作應(yīng)進(jìn)一步抽取,通過函數(shù)的調(diào)用來體現(xiàn)流程。
特定算法等不可分割的邏輯允許例外。
示例:
function syncViewStateOnUserAction() { if (x.checked) { y.checked = true; z.value = ""; } else { y.checked = false; } if (a.value) { warning.innerText = ""; submitButton.disabled = false; } else { warning.innerText = "Please enter it"; submitButton.disabled = true; } } // 直接閱讀該函數(shù)會(huì)難以明確其主線邏輯,因此下方是一種更合理的表達(dá)方式: function syncViewStateOnUserAction() { syncXStateToView(); checkAAvailability(); } function syncXStateToView() { y.checked = x.checked; if (x.checked) { z.value = ""; } } function checkAAvailability() { if (a.value) { clearWarnignForA(); } else { displayWarningForAMissing(); } }2.8.2參數(shù)設(shè)計(jì) [建議] 一個(gè)函數(shù)的參數(shù)控制在 6 個(gè)以內(nèi)。
解釋:
除去不定長參數(shù)以外,函數(shù)具備不同邏輯意義的參數(shù)建議控制在 6 個(gè)以內(nèi),過多參數(shù)會(huì)導(dǎo)致維護(hù)難度增大。
某些情況下,如使用 AMD Loader 的 require 加載多個(gè)模塊時(shí),其 callback 可能會(huì)存在較多參數(shù),因此對(duì)函數(shù)參數(shù)的個(gè)數(shù)不做強(qiáng)制限制。
解釋:
有些函數(shù)的參數(shù)并不是作為函數(shù)邏輯的輸入,而是對(duì)函數(shù)邏輯的某些分支條件判斷之用,此類參數(shù)建議通過一個(gè) options 參數(shù)傳遞。
如下函數(shù):
/** * 移除某個(gè)元素 * * @param {Node} element 需要移除的元素 * @param {boolean} removeEventListeners 是否同時(shí)將所有注冊(cè)在元素上的事件移除 */ function removeElement(element, removeEventListeners) { element.parent.removeChild(element); if (removeEventListeners) { element.clearEventListeners(); } }
可以轉(zhuǎn)換為下面的簽名:
/** * 移除某個(gè)元素 * * @param {Node} element 需要移除的元素 * @param {Object} options 相關(guān)的邏輯配置 * @param {boolean} options.removeEventListeners 是否同時(shí)將所有注冊(cè)在元素上的事件移除 */ function removeElement(element, options) { element.parent.removeChild(element); if (options.removeEventListeners) { element.clearEventListeners(); } }
這種模式有幾個(gè)顯著的優(yōu)勢:
boolean 型的配置項(xiàng)具備名稱,從調(diào)用的代碼上更易理解其表達(dá)的邏輯意義。
當(dāng)配置項(xiàng)有增長時(shí),無需無休止地增加參數(shù)個(gè)數(shù),不會(huì)出現(xiàn) removeElement(element, true, false, false, 3) 這樣難以理解的調(diào)用代碼。
當(dāng)部分配置參數(shù)可選時(shí),多個(gè)參數(shù)的形式非常難處理重載邏輯,而使用一個(gè) options 對(duì)象只需判斷屬性是否存在,實(shí)現(xiàn)得以簡化。
示例:
// good function yup(name, options, args) { // ...stuff... } // bad function nope(name, options, arguments) { // ...stuff... }2.9面向?qū)ο?/b> [強(qiáng)制] 類的繼承方案,實(shí)現(xiàn)時(shí)需要修正 constructor。
解釋:
通常使用其他 library 的類繼承方案都會(huì)進(jìn)行 constructor 修正。如果是自己實(shí)現(xiàn)的類繼承方案,需要進(jìn)行 constructor 修正。
示例:
/** * 構(gòu)建類之間的繼承關(guān)系 * * @param {Function} subClass 子類函數(shù) * @param {Function} superClass 父類函數(shù) */ function inherits(subClass, superClass) { var F = new Function(); F.prototype = superClass.prototype; subClass.prototype = new F(); subClass.prototype.constructor = subClass; }[建議] 聲明類時(shí),保證 constructor 的正確性。
示例:
function Animal(name) { this.name = name; } // 直接prototype等于對(duì)象時(shí),需要修正constructor Animal.prototype = { constructor: Animal, jump: function () { alert("animal " + this.name + " jump"); } }; // 這種方式擴(kuò)展prototype則無需理會(huì)constructor Animal.prototype.jump = function () { alert("animal " + this.name + " jump"); };[建議] 屬性在構(gòu)造函數(shù)中聲明,方法在原型中聲明。
解釋:
原型對(duì)象的成員被所有實(shí)例共享,能節(jié)約內(nèi)存占用。所以編碼時(shí)我們應(yīng)該遵守這樣的原則:原型對(duì)象包含程序不會(huì)修改的成員,如方法函數(shù)或配置項(xiàng)。
function TextNode(value, engine) { this.value = value; this.engine = engine; } TextNode.prototype.clone = function () { return this; };[建議] 自定義事件的 事件名 必須全小寫。
解釋:
在 JavaScript 廣泛應(yīng)用的瀏覽器環(huán)境,絕大多數(shù) DOM 事件名稱都是全小寫的。為了遵循大多數(shù) JavaScript 開發(fā)者的習(xí)慣,在設(shè)計(jì)自定義事件時(shí),事件名也應(yīng)該全小寫。
解釋:
一個(gè)事件對(duì)象的好處有:
順序無關(guān),避免事件監(jiān)聽者需要記憶參數(shù)順序。
每個(gè)事件信息都可以根據(jù)需要提供或者不提供,更自由。
擴(kuò)展方便,未來添加事件信息時(shí),無需考慮會(huì)破壞監(jiān)聽器參數(shù)形式而無法向后兼容。
[建議] 設(shè)計(jì)自定義事件時(shí),應(yīng)考慮禁止默認(rèn)行為。解釋:
常見禁止默認(rèn)行為的方式有兩種:
事件監(jiān)聽函數(shù)中 return false。
事件對(duì)象中包含禁止默認(rèn)行為的方法,如 preventDefault。
2.10 動(dòng)態(tài)特性 2.10.1 eval [強(qiáng)制] 避免使用直接 eval 函數(shù)。解釋:
直接 eval,指的是以函數(shù)方式調(diào)用 eval 的調(diào)用方法。直接 eval 調(diào)用執(zhí)行代碼的作用域?yàn)楸镜刈饔糜?,?yīng)當(dāng)避免。
如果有特殊情況需要使用直接 eval,需在代碼中用詳細(xì)的注釋說明為何必須使用直接 eval,不能使用其它動(dòng)態(tài)執(zhí)行代碼的方式,同時(shí)需要其他資深工程師進(jìn)行 Code Review。
解釋:
使用 with 可能會(huì)增加代碼的復(fù)雜度,不利于閱讀和管理;也會(huì)對(duì)性能有影響。大多數(shù)使用 with 的場景都能使用其他方式較好的替代。所以,盡量不要使用 with。
解釋:
對(duì)于有被遍歷需求,且值 null 被認(rèn)為具有業(yè)務(wù)邏輯意義的值的對(duì)象,移除某個(gè)屬性必須使用 delete 操作。
在嚴(yán)格模式或 IE 下使用 delete 時(shí),不能被刪除的屬性會(huì)拋出異常,因此在不確定屬性是否可以刪除的情況下,建議添加 try-catch 塊。
示例:
try { delete o.x; } catch (deleteError) { o.x = null; }2.10.4對(duì)象屬性 [建議] 避免修改外部傳入的對(duì)象。
解釋:
JavaScript 因其腳本語言的動(dòng)態(tài)特性,當(dāng)一個(gè)對(duì)象未被 seal 或 freeze 時(shí),可以任意添加、刪除、修改屬性值。
但是隨意地對(duì) 非自身控制的對(duì)象 進(jìn)行修改,很容易造成代碼在不可預(yù)知的情況下出現(xiàn)問題。因此,設(shè)計(jì)良好的組件、函數(shù)應(yīng)該避免對(duì)外部傳入的對(duì)象的修改。
下面代碼的 selectNode 方法修改了由外部傳入的 datasource 對(duì)象。如果 datasource 用在其它場合(如另一個(gè) Tree 實(shí)例)下,會(huì)造成狀態(tài)的混亂。
function Tree(datasource) { this.datasource = datasource; } Tree.prototype.selectNode = function (id) { // 從datasource中找出節(jié)點(diǎn)對(duì)象 var node = this.findNode(id); if (node) { node.selected = true; this.flushView(); } };
對(duì)于此類場景,需要使用額外的對(duì)象來維護(hù),使用由自身控制,不與外部產(chǎn)生任何交互的 selectedNodeIndex 對(duì)象來維護(hù)節(jié)點(diǎn)的選中狀態(tài),不對(duì) datasource 作任何修改。
function Tree(datasource) { this.datasource = datasource; this.selectedNodeIndex = {}; } Tree.prototype.selectNode = function (id) { // 從datasource中找出節(jié)點(diǎn)對(duì)象 var node = this.findNode(id); if (node) { this.selectedNodeIndex[id] = true; this.flushView(); } };
除此之外,也可以通過 deepClone 等手段將自身維護(hù)的對(duì)象與外部傳入的分離,保證不會(huì)相互影響。
[建議] 具備強(qiáng)類型的設(shè)計(jì)。解釋:
如果一個(gè)屬性被設(shè)計(jì)為 boolean 類型,則不要使用 1 或 0 作為其值。對(duì)于標(biāo)識(shí)性的屬性,如對(duì)代碼體積有嚴(yán)格要求,可以從一開始就設(shè)計(jì)為 number 類型且將 0 作為否定值。
從 DOM 中取出的值通常為 string 類型,如果有對(duì)象或函數(shù)的接收類型為 number 類型,提前作好轉(zhuǎn)換,而不是期望對(duì)象、函數(shù)可以處理多類型的值。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/83710.html
摘要:這樣的變量增加了代碼量,并且混淆讀者。錯(cuò)誤代碼示例變量雖然聲明了,但沒被使用持續(xù)更新 JavaScript 編碼規(guī)范 一、命名規(guī)范 1. 變量 命名方法:小駝峰式命名法(由小寫字母開始,后續(xù)每個(gè)單詞首字母都大寫) 命名建議:語義化的名詞 特殊:布爾值變量建議添加符合其含義的前綴動(dòng)詞 is:是否 can:能不能 has:有沒有 示例: // 頁面標(biāo)題 let pageT...
摘要:示例強(qiáng)制對(duì)中規(guī)定允許省略的閉合標(biāo)簽,不允許省略閉合標(biāo)簽。示例圖片強(qiáng)制禁止的取值為空。示例提交取消取消提交建議當(dāng)使用進(jìn)行表單提交時(shí),如果條件允許,應(yīng)使原生提交功能正常工作。示例建議模板代碼應(yīng)以保證單個(gè)標(biāo)簽語法的正確性為基本原則。 這段時(shí)間在整理前端部分代碼規(guī)范,初步想法是從HTML、CSS、Javascipt、項(xiàng)目文件目錄四部分是整理。之前已經(jīng)整理完了CSS編碼規(guī)范,有興趣可以了解下 1...
摘要:指定參數(shù)為可以獲得所有子元素。如需多次操作同一集合,則應(yīng)將集合轉(zhuǎn)為數(shù)組。示例顯示為顯示為建議獲取元素的直接子元素時(shí)使用。建議盡量減少操作。事件建議優(yōu)先使用綁定事件,避免直接在屬性中或的屬性綁定事件處理。而的僅支持冒泡的事件觸發(fā)。 轉(zhuǎn)載:原地址 4 瀏覽器環(huán)境 4.1 模塊化 4.1.1 AMD [強(qiáng)制] 使用 AMD 作為模塊定義。 解釋: AMD 作為由社區(qū)認(rèn)可的模塊定義...
摘要:當(dāng)然我們還可以引入框架,這些框架一般都自帶模板處理引擎,比如等語義化命名和語義化標(biāo)簽我們盡量多采用語義化來命名,并且采用語義化標(biāo)簽來書寫代碼,多用中新增的標(biāo)簽來書寫。 1.黃金法則(Golden rule) 不管有多少人參與同一個(gè)項(xiàng)目,一定要確保每一行代碼都像是同一個(gè)人編寫的。 Every line of code should appear to be written by a si...
摘要:示例強(qiáng)制禁止為了腳本,創(chuàng)建無樣式信息的。示例強(qiáng)制對(duì)中規(guī)定允許省略的閉合標(biāo)簽,不允許省略閉合標(biāo)簽。指定字符編碼的必須是的第一個(gè)直接子元素。示例提交取消取消提交建議當(dāng)使用進(jìn)行表單提交時(shí),如果條件允許,應(yīng)使原生提交功能正常工作。 轉(zhuǎn)載:原地址 1 前言 HTML作為描述網(wǎng)頁結(jié)構(gòu)的超文本標(biāo)記語言,在百度一直有著廣泛的應(yīng)用。本文檔的目標(biāo)是使HTML代碼風(fēng)格保持一致,容易被理解和被維護(hù)。 2 代碼...
閱讀 3007·2023-04-26 01:01
閱讀 3757·2021-11-23 09:51
閱讀 2572·2021-11-22 14:44
閱讀 3782·2021-09-23 11:57
閱讀 2914·2021-09-22 14:58
閱讀 5952·2021-09-10 11:25
閱讀 2186·2019-08-30 13:11
閱讀 1648·2019-08-30 12:59