# JavaScript編碼標準
JavaScript已經成為開發基于WordPress的應用程序(主題和插件)以及WordPress核心的關鍵組件。格式化和造型JavaScript代碼需要標準來保持與WordPress標準提供的核心PHP,HTML和CSS代碼相同的代碼一致性。
任何代碼庫中的所有代碼應該看起來像一個人打字,無論有多少人貢獻。 - 寫作一致,慣用JavaScript的原則
WordPress JavaScript編碼標準是從jQuery JavaScript樣式指南中進行的。我們的標準與jQuery指南在以下方面不同:
- WordPress使用單引號來進行字符串聲明。
- Case語句在切換塊中縮進。
- 函數內容始終縮小,包括全文件封閉包裝器。
- 一些空格規則不一致,與WordPress PHP編碼標準保持一致。
- 鼓勵jQuery的100字符硬線限制,但不會嚴格執行。
下面的很多例子直接從jQuery風格指南中進行了調整;這些差異已經被整合到這個頁面上的例子中。以下任何標準和示例應被視為WordPress代碼的最佳做法,除非明確指出為反模式。
## 代碼重構
>“代碼重構不應該只是因為我們可以做到。” - Lead Developer Andrew Nacin
JavaScript的WordPress代碼結構的許多部分的風格不一致。 WordPress正在努力逐步改進這一點,所以代碼將一覽無余,易于閱讀。
雖然編碼標準很重要,但重構舊的.js文件只是為了符合標準不是一個緊迫的問題。強烈建議不要使用舊的文件“僅空白”補丁。
所有新的或更新的JavaScript代碼將被審查,以確保它符合標準,并通過JSHint。
## 間距
在你的代碼中使用空格。 “當有疑問的時候,空間就出來了。
這些規則鼓勵自由空間提高開發者的可讀性。縮小過程創建一個文件,該文件針對瀏覽器進行了優化,以進行讀取和處理。
- 用標簽縮進。
- 在行尾或空白行沒有空格。
- 線條通常不應超過80個字符,不應超過100個(將標簽計數為4個空格)。這是一個“軟”規則,但長行通常表示不可讀或無組織的代碼。
- 如果/ else / for / while / try塊應該總是使用大括號,并且始終在多行上。
- 一元的特殊字符運算符(例如,++, - )不能在它們的操作數旁邊有空格。
- 任何和不得有上一個空格。
- 任何 ;用作聲明終止符必須在行尾。
- 任何:在對象定義中的屬性名后面不得有前面的空格。并且:在三元條件下,雙方必須有空間。空構造中沒有填充空間(例如{},[],fn())。
- 每個文件末尾應該有一行。
- 任何 !否定運算符應具有以下空格。
- 所有功能體都縮進一個選項卡,即使整個文件被封裝在一起。
- 空格可以在文檔塊內或行內對齊代碼,但只能在行的開頭使用選項卡。
>[warning] WordPress JavaScript標準比jQuery樣式指南更傾向于略寬的空白規則。這些偏差是WordPress代碼庫中PHP和JavaScript文件之間的一致性。
空格可以輕松地累積在行的末尾 - 避免這一點,因為尾隨的空格被捕獲為JSHint中的錯誤。捕獲空格累積的一種方法是在文本編輯器中啟用可見的空白字符。
## 對象
如果對象聲明很短,可以在一行上進行對象聲明(記住行長度指南)。當一個對象聲明太長而不能適合一行時,每行必須有一個屬性。如果屬性名稱是保留字或包含特殊字符,則只需引用屬性名稱:
```
// Preferred
var map = {
ready: 9,
when: 4,
'you are': 15
};
// Acceptable for small objects
var map = { ready: 9, when: 4, 'you are': 15 };
// Bad
var map = { ready: 9,
when: 4, 'you are': 15 };
```
## 數組和函數調用
在元素和參數上總是包含多余的空格:
```
array = [ a, b ];
foo( arg );
foo( 'string', object );
foo( options, object[ property ] );
foo( node, 'property', 2 );
```
**例外:**
```
// For consistency with our PHP standards, do not include a space around
// string literals or integers used as key values in array notation:
prop = object['default'];
firstArrayElement = arr[0];
// Function with a callback, object, or array as the sole argument:
// No space on either side of the argument
foo(function() {
// Do stuff
});
foo({
a: 'alpha',
b: 'beta'
});
foo([
'alpha',
'beta'
]);
// Function with a callback, object, or array as the first argument:
// No space before the first argument
foo(function() {
// Do stuff
}, options );
// Function with a callback, object, or array as the last argument:
// No space after after the last argument
foo( data, function() {
// Do stuff
});
```
## 良好間距的示例
```javascript
var i;
if ( condition ) {
doSomething( 'with a string' );
} else if ( otherCondition ) {
otherThing({
key: value,
otherKey: otherValue
});
} else {
somethingElse( true );
}
// Unlike jQuery, WordPress prefers a space after the ! negation operator.
// This is also done to conform to our PHP standards.
while ( ! condition ) {
iterating++;
}
for ( i = 0; i < 100; i++ ) {
object[ array[ i ] ] = someFn( i );
$( '.container' ).val( array[ i ] );
}
try {
// Expressions
} catch ( e ) {
// Expressions
}
```
## 分號
使用它們。 不要依靠自動分號插入(ASI)。
## 縮進和換行符
縮進和換行符增加了對復雜語句的可讀性。
標簽應用于縮進。 即使整個文件包含在一個閉包(即一個立即被調用的函數)中,該函數的內容應該被一個tab縮進:
```
(function( $ ) {
// Expressions indented
function doSomething() {
// Expressions indented
}
})( jQuery );
```
## 塊和大括號
如果,其他,for,while和try塊應該始終使用大括號,并且始終在多行。 開放大括號應與功能定義,條件或循環在同一行。 關閉括號應該直接跟隨塊的最后一個語句。
```
var a, b, c;
if ( myFunction() ) {
// Expressions
} else if ( ( a && b ) || c ) {
// Expressions
} else {
// Expressions
}
```
## 多行語句
當一個語句太長而不能適合一行,換行符必須在操作符之后發生。
```
// Bad
var html = '<p>The sum of ' + a + ' and ' + b + ' plus ' + c
+ ' is ' + ( a + b + c );
// Good
var html = '<p>The sum of ' + a + ' and ' + b + ' plus ' + c +
' is ' + ( a + b + c );
```
如果提高可讀性,則將行分解為邏輯組,例如將三元運算符的每個表達式分割到其自己的行上,即使兩者都適合單行。
```
// Acceptable
var baz = ( true === conditionalStatement() ) ? 'thing 1' : 'thing 2';
// Better
var baz = firstCondition( foo ) && secondCondition( bar ) ?qux( foo, bar ):foo;
```
當條件太長而不能適合一行時,連續的行必須縮進一個額外的級別以將其與身體區分開來。
```
if ( firstCondition() && secondCondition() &&
thirdCondition() ) {
doStuff();
}
```
## 鏈接方法調用
當一連串的方法調用太長時間不適合一行,每行必須有一個調用,第一個調用與調用方法的對象分開。 如果方法更改上下文,則必須使用額外的縮進級別。
```
elements
.addClass( 'foo' )
.children()
.html( 'hello' )
.end()
.appendTo( 'body' );
```
## var聲明變量和全局變量
### 用var聲明變量
每個函數應該以一個逗號分隔的var語句開始,該語句聲明任何必需的局部變量。 如果函數沒有使用var聲明變量,則該變量可能會泄漏到外部范圍(通常是全局范圍,最壞情況),并且可能會無意間引用并修改該數據。
var語句中的賦值應該列在單獨的行上,而聲明可以分組在一行。 任何額外的行應該縮進一個額外的選項卡。 占用多個行的對象和函數應該被分配到var語句之外,以避免過度縮進。
```
// Good
var k, m, length,
// Indent subsequent lines by one tab
value = 'WordPress';
// Bad
var foo = true;
var bar = false;
var a;
var b;
var c;
```
### 全局變量
在過去,WordPress核心使用更大的全局變量。 由于內核JavaScript文件有時在插件中使用,所以現有的全局變量不應該被刪除。
文件中使用的所有全局變量都應記錄在該文件的頂部。 多個全局變量可以以逗號分隔。
這個例子會使passwordStrength是該文件中允許的全局變量:
/* global passwordStrength:true */
passwordStrength之后的“true”表示在此文件中定義了該全局。 如果要訪問在其他地方定義的全局,請省略:將全局指定為只讀。
**公共庫**
Backbone,jQuery,Underscore和全局wp對象都被注冊為根.jshintrc文件中的允許全局變量。
Backbone和Underscore可以隨時直接訪問。 jQuery應該通過$通過將jQuery對象傳遞給匿名函數來訪問:
```
(function( $ ) {
// Expressions
})( jQuery );
```
這將無效調用.noConflict()或使用另一個變量設置$。
添加或修改wp對象的文件必須安全地訪問全局,以避免覆蓋以前設置的屬性:
```
// At the top of the file, set "wp" to its existing value (if present)
window.wp = window.wp || {};
```
## 命名約定
變量和函數名稱應該是完整的單詞,使用小寫第一個字母的駱駝殼。 這個標準與WordPress PHP編碼標準不同。
要用于new的構造函數應該有一個大寫的第一個字母(UpperCamelCase)。
名稱應該是描述性的,但不是過分的。 允許迭代器使用異常,例如使用i來表示循環中的索引。
## 注釋
注釋來自他們引用的代碼,并且應該始終以空行為前。 注釋評論的第一個字母,并在寫完整句時包括一段時間。 注釋標記(//)和注釋文本之間必須有一個空格。
單行注釋:
```
// Explanation of something complex on the next line
$( 'p' ).doSomething();
```
多行注釋應用于長期注釋,另請參閱JavaScript文檔標準:
```
/*
* This is a comment that is long enough to warrant being stretched
* over the span of multiple lines.
*/
```
使用內聯注釋作為異常,用于在形式參數列表中注釋特殊參數:
```
function foo( types, selector, data, fn, /* INTERNAL */ one ) {
// Do stuff
}
```
## 比較符
必須使用嚴格的等式檢查(===)來有利于抽象等價檢查(==)。 唯一的例外是通過null檢查undefined和null。
```
// Check for both undefined and null values, for some important reason.
if ( undefOrNull == null ) {
// Expressions
}
```
## 類型檢察
這些是檢查對象類型的首選方法:
- String: typeof object === 'string'
- Number: typeof object === 'number'
- Boolean: typeof object === 'boolean'
- Object: typeof object === 'object' or _.isObject( object )
- Plain Object: jQuery.isPlainObject( object )
- Function: _.isFunction( object) or jQuery.isFunction( object )
- Array: _.isArray( object ) or jQuery.isArray( object )
- Element: object.nodeType or _.isElement( object )
- null: object === null
- null or undefined: object == null
**undefined:**
- Global Variables: typeof variable === 'undefined'
- Local Variables: variable === undefined
- Properties: object.prop === undefined
- Any of the above: _.isUndefined( object )
隨著任何骨干或下劃線已經被使用,我們鼓勵您使用Underscore.js的類型檢查方法來使用jQuery。
## 字符串
對字符串文字使用單引號:
```
var myStr = 'strings should be contained in single quotes';
```
當字符串包含單引號時,需要使用反斜杠(\)進行轉義:
```
// Escape single quotes within strings:
'Note the backslash before the \'single quotes\'';
```
## Switch語句
通常不鼓勵使用switch語句,但是在有大量情況下可能會很有用 - 特別是當可以通過相同的塊處理多個情況時,或者可以利用掉線邏輯(默認情況)。
使用switch語句時:
- 對于每個案例,除了默認使用中斷。 當允許語句“通過”時,明確指出。
- 縮進案例語句開關內的一個選項卡。
```
switch ( event.keyCode ) {
// ENTER and SPACE both trigger x()
case $.ui.keyCode.ENTER:
case $.ui.keyCode.SPACE:
x();
break;
case $.ui.keyCode.ESCAPE:
y();
break;
default:
z();
}
```
>[info] 不建議從switch語句中返回值:使用case塊來設置值,然后在最后返回這些值。
```
function getKeyCode( keyCode ) {
var result;
switch ( event.keyCode ) {
case $.ui.keyCode.ENTER:
case $.ui.keyCode.SPACE:
result = 'commit';
break;
case $.ui.keyCode.ESCAPE:
result = 'exit';
break;
default:
result = 'default';
}
return result;
}
```
## 最佳做法
### 數組
在JavaScript中創建數組應該使用shorthand []構造函數而不是新的Array()表示法來完成。
```
var myArray = [];
```
您可以在構建期間初始化數組:
```
var myArray = [ 1, 'WordPress', 2, 'Blog' ];
```
在JavaScript中,關聯數組被定義為對象。
### 對象
有很多方法可以在JavaScript中創建對象。 對象字面符號{},既是最具性能的,也是最容易閱讀的。
```
var myObj = {};
```
應該使用對象字面符號,除非對象需要特定的原型,在這種情況下,應該通過使用new調用構造函數來創建對象。
```
var myObj = new ConstructorMethod();
```
應通過`.`表示法訪問對象屬性,除非該鍵是變量,保留字或不是有效標識符的字符串:
```
prop = object.propertyName;
prop = object[ variableKey ];
prop = object['default'];
prop = object['key-with-hyphens'];
```
## 條件
為了與PHP代碼標準保持一致,無論何時將對象與字符串,布爾值,整數或其他常量或字面值進行比較,變量應始終放在右側,常量或常量放在左側。
```
if ( true === myCondition ) {
// Do stuff
}
```
“有點奇怪,就是閱讀。 習慣了,你會的。“
## 迭代
當使用for循環遍歷大型集合時,建議將循環的最大值存儲為變量,而不是每次重新計算最大值:
```
// Good & Efficient
var i, max;
// getItemCount() gets called once
for ( i = 0, max = getItemCount(); i < max; i++ ) {
// Do stuff
}
// Bad & Potentially Inefficient:
// getItemCount() gets called every time
for ( i = 0; i < getItemCount(); i++ ) {
// Do stuff
}
```
## Underscore.js集合函數
了解和了解Underscore的集合和數組方法。 這些函數(包括_.each,_.map和_.reduce)允許大數據集的高效,可讀的變換。
下劃線還允許使用常規JavaScript對象進行jQuery樣式鏈接:
```
var obj = {
first: 'thing 1',
second: 'thing 2',
third: 'lox'
};
var arr = _.chain( obj )
.keys()
.map(function( key ) {
return key + ' comes ' + obj[ key ];
})
// Exit the chain
.value();
// arr === [ 'first comes thing 1', 'second comes thing 2', 'third comes lox' ]
```
## 迭代jQuery集合
jQuery應該用于迭代的唯一時間是迭代jQuery對象的集合:
```
$tabs.each(function( index, element ) {
var $element = $( element );
// Do stuff to $element
});
```
不要使用jQuery遍歷原始數據或者是vanilla JavaScript對象。
## JSHint
JSHint是一種自動化的代碼質量工具,旨在捕獲JavaScript代碼中的錯誤。 JSHint用于WordPress開發,以快速驗證補丁沒有向前端引入任何邏輯或語法錯誤。
### 安裝和運行JSHint
JSHint使用名為Grunt的工具運行。 JSHint和Grunt都是在Node.js中編寫的程序。 WordPress開發代碼隨附的配置文件可以輕松安裝和配置這些工具。
要安裝Node.js,請單擊節點網站上的安裝鏈接。您的操作系統的正確安裝文件將被下載。按照操作系統的安裝步驟安裝程序。
一旦安裝了Node.js,打開命令行窗口并導航到您簽出WordPress SVN存儲庫副本的目錄(使用cd?/ directoryname)。您應該在包含package.json文件的根目錄中。
接下來,在命令行窗口中輸入npm install。這將下載并安裝WordPress開發中使用的所有Node軟件包。
最后,鍵入npm install -g grunt-cli來安裝Grunt命令行界面(CLI)包。 Grunt CLI是用于在WordPress中實際運行Grunt任務的。
您現在應該能夠輸入grunt jshint以使Grunt檢查所有WordPress JavaScript文件的語法和邏輯錯誤。要檢查核心代碼,請鍵入grunt jshint:core;只檢查單元測試.js文件,鍵入grunt jshint:tests。
### JSHint設置
用于JSHint的配置選項存儲在WordPress SVN存儲庫中的.jshintrc文件中。該文件定義JSHint應該在WordPress源代碼中找到它們時應該標記哪些錯誤。
### 定位單個文件
要為JSHint指定單個文件進行檢查,請在命令的末尾添加--file = filename.js。例如,這只會在WordPress的核心JavaScript文件中檢查名為“admin-bar.js”的文件:
grunt jshint:core --file = admin-bar.js
這只會檢查單元測試目錄中的“password-strength-meter.js”文件:
grunt jshint:tests --file = password-strength-meter.js
將JSHint限制為單個文件可能會有用,如果您只處理一個或兩個特定文件,并且不希望JSHint在每次運行時等待每個文件處理。
### JSHint覆蓋:忽略塊
在某些情況下,文件的部分應該從JSHint中排除。作為示例,管理欄的腳本文件包含jQuery HoverIntent插件的最小化代碼 - 這是不應通過JSHint的第三方代碼,盡管它是WordPress核心JavaScript文件的一部分。
要排除JSHint處理的特定文件區域,請將其包含在JSHint指令注釋中:
```
/* jshint ignore:start */
if ( typeof jQuery.fn.hoverIntent === 'undefined' ) {
// hoverIntent r6 - Copy of wp-includes/js/hoverIntent.min.js
(function(a){a.fn.hoverIntent=...............
}
/* jshint ignore:end */
```
- 簡介
- 主題開發
- WordPress許可證
- 什么是主題
- 開發環境
- 主題開發示例
- 主題基礎
- 模板文件
- 主樣式表(style.css)
- 文章類型
- 規劃主題文件
- 模板層級
- 模板標簽
- 循環
- 主題函數
- 連接主題文件和目錄
- 使用CSS和JavaScript
- 條件標簽
- 類別,標簽和自定義分類
- 模板文件
- 內容模板文件
- 頁面模板文件
- 附件模板文件
- 自定義內容類型
- 部分和其他模板文件
- 評論模板
- 分類模板
- 404頁面
- 主題功能
- 核心支持的功能
- 管理菜單
- 自定義Headers
- 自定義Logo
- 文章格式
- 置頂文章
- Sidebars
- Widgets
- 導航菜單
- 分頁
- 媒體
- Audio
- Images
- Galleries
- Video
- 精選圖片和縮略圖
- 國際化
- 本地化
- 輔助功能
- 主題選項 – 自定義API
- 定制對象
- 改進用戶體驗的工具
- 定制JavaScript API
- JavaScript / Underscore.js渲染的自定義控件
- 高級用法
- 主題安全
- 數據消毒/逃避
- 數據驗證
- 使用隨機數
- 常見漏洞
- 高級主題
- 子主題
- UI最佳實踐
- JavaScript最佳做法
- 主題單元測試
- 驗證你的主題
- Plugin API Hooks
- 發布你的主題
- 所需的主題文件
- 測試
- 主題評論指南
- 寫文檔
- 提交你的主題到WordPress.org
- 參考文獻
- 模板標簽列表
- 條件標簽列表
- 編碼標準
- HTML編碼標準
- CSS編碼標準
- JavaScript編碼標準
- PHP編碼標準
- 插件開發
- 插件開發簡介
- 什么是插件
- 插件基礎
- 頭部要求
- 包括軟件許可證
- 啟用 / 停用 Hooks
- 卸載方法
- 最佳做法
- 插件安全
- 檢查用戶功能
- 數據驗證
- 保護輸入
- 保護輸出
- 隨機數
- Hooks
- Actions
- Filters
- 自定義Hooks
- 高級主題
- 管理菜單
- 頂級菜單
- 子菜單
- 短代碼
- 基本短碼
- 封閉短碼
- 帶參數的短代碼
- TinyMCE增強型短碼
- 設置
- 設置API
- 使用設置API
- 選項API
- 自定義設置頁面
- 元數據
- 管理帖子元數據
- 自定義元數據
- 渲染元數據
- 自定義文章類型
- 注冊自定義文章類型
- 使用自定義文章類型
- 分類
- 使用自定義分類
- 在WP 4.2+中使用“split術語”
- 用戶
- 創建和管理用戶
- 使用用戶元數據
- 角色和功能
- HTTP API
- JavaScript
- jQuery
- Ajax
- 服務器端PHP和入隊
- Heartbeat API
- 概要
- 計劃任務
- 了解WP-Cron計劃
- 安排WP-Cron 事件
- 將WP-Cron掛接到系統任務計劃程序中
- WP-Cron簡單測試
- 國際化
- 本地化
- 如何國際化您的插件
- 國際化安全
- WordPress.org
- 詳細插件指南
- 規劃您的插件
- 如何使用Subversion
- 插件開發者常見問題
- 開發工具
- Debug Bar 和附加組件
- 輔助插件
- REST API手冊
- 資源
- 文章
- 文章修訂
- 文章類型
- 文章狀態
- 類別
- 標簽
- 頁面
- 評論
- 分類
- 媒體
- 用戶
- 設置
- 使用REST API
- 全局參數
- 分頁
- 鏈接和嵌入
- 發現
- 認證
- 經常問的問題
- 骨干JavaScript客戶端
- 客戶端庫
- 擴展REST API
- 添加自定義端點
- 自定義內容類型
- 修改回應
- 模式
- 詞匯表
- 路由和端點
- 控制器類