# 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
- 添加自定义端点
- 自定义内容类型
- 修改回应
- 模式
- 词汇表
- 路由和端点
- 控制器类