WordPress开发编码规范——JavaScript编码标准

JavaScript已成为开发基于WordPress的应用程序(主题和插件)以及WordPress核心的关键组件。格式化和样式化JavaScript代码需要标准,以保持与WordPress标准为核心PHP,HTML和CSS代码提供的相同代码一致性。

无论有多少人参与,任何代码库中的所有代码都应该看起来像是一个人键入的代码。– 一致的惯用JavaScript编写原则

WordPress JavaScript编码标准改编自jQuery JavaScript样式指南。我们的标准在以下方面与jQuery准则不同:

  • WordPress对字符串声明使用单引号。
  • Case语句在开关块内缩进。
  • 函数内容始终缩进,包括完整文件的封闭包装。
  • 一些空白规则有所不同,以与WordPress PHP编码标准保持一致。
  • 鼓励使用jQuery的100个字符的硬线限制,但不严格执行。

下面的许多示例都直接从jQuery样式指南改编而来;这些差异都已集成到此页面的示例中。除非明确指出是反模式,否则以下任何标准和示例都应被视为WordPress代码的最佳做法。

代码重构

用于JavaScript的WordPress代码结构的许多部分在样式上不一致。WordPress正在努力逐步改善这一点,因此该代码将一目了然且易于阅读。

尽管编码标准很重要,但是重构旧的.js文件以使其符合标准并不是紧迫的问题。强烈建议不要使用较旧文件的“仅空白”补丁。

所有新的或更新的JavaScript代码都将接受审查,以确保其符合标准,并通过JSHint。

间距

在代码中自由使用空格。“有疑问时,将其隔开。”

这些规则鼓励自由的间距,以提高开发人员的可读性。缩小过程将创建一个文件,该文件针对浏览器进行了优化阅读和处理。

  • 带标签的缩进。
  • 行尾或空行上没有空格。
  • 行通常不应超过80个字符,并且不应超过100个字符(将制表符计为4个空格)。这是一个“软”规则,但是长线通常表示不可读或混乱的代码。
  • ifelseforwhiletry块应该总是使用大括号,并始终走多条线路上。
  • 一元特殊字符运营商(例如++--),不能有自己的空间,操作旁边。
  • 任何,,;不得有前面的空格。
  • 任何;用作语句终止符的行都必须在该行的末尾。
  • :对象定义中的属性名称后面的任何空格都不能包含前导空格。
  • 三元条件中的?:两侧必须有空格。
  • 在空构造无填料空间(例如{}[]fn())。
  • 每个文件的末尾应有一个新行。
  • 任何!否定运算符都应有以下空格。*
  • 即使整个文件都包装在一个闭包中,所有功能主体都由一个选项卡缩进。*
  • 空格可以使文档块内或行中的代码对齐,但是在行的开头应仅使用制表符。*

*:WordPress JavaScript标准比jQuery样式指南更喜欢更宽的空格规则。这些偏差是为了确保WordPress代码库中的PHP和JavaScript文件之间的一致性。

空格很容易在行尾累积–避免这种情况,因为在JSHint中将尾随空格捕获为错误。捕获空白的一种方法是在文本编辑器中启用可见的空白字符。

对象

如果对象声明很短,则可以在一行上进行声明(请记住行长准则)。如果对象声明太长而无法容纳在一行上,则每行必须有一个属性。属性名称仅在保留字或包含特殊字符的情况下才需要加引号:

如果对象和数组很短,则可以在一行上声明它们(请记住行长准则)。如果对象或数组太长而无法容纳在一行上,则每个成员必须放在自己的行上,并且每行以逗号结尾。

// Preferred
var obj = {
    ready: 9,
    when: 4,
    'you are': 15,
};
var arr = [
    9,
    4,
    15,
];
 
// Acceptable for small objects and arrays
var obj = { ready: 9, when: 4, 'you are': 15 };
var arr = [ 9, 4, 15 ];
 
// Bad
var obj = { ready: 9,
    when: 4, 'you are': 15 };
var arr = [ 9,
    4, 15 ];

数组和函数调用

始终在元素和参数周围包含额外的空格:

array = [ a, b ];
 
foo( arg );
 
foo( 'string', object );
 
foo( options, object[ property ] );
 
foo( node, 'property', 2 );
 
prop = object[ 'default' ];
 
firstArrayElement = arr[ 0 ];

良好的间距举例

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)。

缩进和换行

缩进和换行符增加了复杂语句的可读性。

制表符应用于缩进。即使整个文件都包含在闭包中(即,立即调用的函数),该函数的内容也应通过一个选项卡缩进:

( function ( $ ) {
    // Expressions indented
 
<pre><code>function doSomething() {
    // Expressions indented
}
</code></pre>
 
} )( jQuery );

块和花括号

ifelseforwhile,和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 ) + '</p>';
 
// Good
var html = '<p>The sum of ' + a + ' and ' + b + ' plus ' + c +
    ' is ' + ( a + b + c ) + '</p>';

如果行提高了可读性,则应将其分成逻辑组,例如将三元运算符的每个表达式拆分为自己的行,即使这两个行都适合于一行。

// 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' );

分配和全局

constlet声明变量

对于代码中使用ES2015或新写的,const并且let应该总是代替使用varconst除非应重新声明其值,否则应使用声明let

不同于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 */

后面的“ true” passwordStrength表示正在此文件中定义此全局变量。如果要访问在其他位置定义的全局变量,请省略:true以将全局变量指定为只读。

公共函数库

Backbone,jQuery,下划线和全局wp对象都在根.jshintrc文件中注册为允许的全局变量。

可以随时直接访问Backbone和下划线。$通过将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编码标准的领域

名称应具有描述性,但不能过多。允许迭代器例外,例如使用i来表示循环中的索引。

缩略语

首字母缩写词必须用大写字母组成。这旨在反映出首字母缩写词的每个字母都是其扩展形式的专有词。

所有其他缩写都必须以驼峰形式书写,首字母大写,后跟小写字母。

如果在变量名的开头出现缩写或首字母缩写词,则必须遵守有关变量或类定义的第一个字母的驼峰命名规则。对于变量分配,这意味着将缩写完全写成小写。对于类的定义,首字母应大写。

// "Id" is an abbreviation of "Identifier":
const userId = 1;
 
// "DOM" is an acronym of "Document Object Model":
const currentDOMDocument = window.document;
 
// Acronyms and abbreviations at the start of a variable name are consistent
// with camelcase rules covering the first letter of a variable or class.
const domDocument = window.document;
class DOMDocument {}
class IdCollection {}

类定义

打算用于的构造函数的new首字母应为大写(UpperCamelCase)。

一个class定义必须使用UpperCamelCase惯例,不管它是否旨在与使用new建筑。

class Earth {
    static addHuman( human ) {
        Earth.humans.push( human );
    }
 
<pre><code>static getHumans() {
    return Earth.humans;
}
</code></pre>
 
}
 
Earth.humans = [];

所有@wordpress/element组件,包括无状态函数组件,都应使用类定义命名规则来命名,以保持一致性并反映出可能需要在不破坏兼容性的情况下将组件从函数转换为类的事实。

常量

在几乎所有情况下,都应在文件的最高级范围内定义一个常量。重要的是要注意,从概念上讲,JavaScript的const分配比此处暗示的要受限制,const在JavaScript中分配的值实际上可以被更改,并且只能防止重新分配。这些编码准则中定义的常量仅适用于期望永不更改的值,并且是开发人员传达意图的一种策略,而不是一种技术限制。

注释

注释位于它们所引用的代码之前,并且应始终在其前空行。大写注释的第一个字母,并在写完整句子时在末尾加句号。注释标记(//)和注释文本之间必须有一个空格。

someStatement();
 
// Explanation of something complex on the next line
$( 'p' ).doSomething();
 
// This is a comment that is long enough to warrant being stretched
// over the span of multiple lines.

JSDoc注释应使用/**多行注释开头。有关更多信息,请参考JavaScript文档标准

当用于注释形式参数列表中的特殊参数时,允许使用内联注释作为例外:

function foo( types, selector, data, fn, /* INTERNAL */ one ) {
    // Do stuff
}

相等比较

严格的相等性检查(===)应优先于抽象相等性检查(==)。

类型检查

这些是检查对象类型的首选方法:

  • 串: typeof object === 'string'
  • 数: typeof object === 'number'
  • 布尔值: typeof object === 'boolean'
  • 对象:typeof object === 'object'_.isObject( object )
  • 普通对象: jQuery.isPlainObject( object )
  • 功能:_.isFunction( object )jQuery.isFunction( object )
  • 数组:_.isArray( object )jQuery.isArray( object )
  • 元素:object.nodeType_.isElement( object )
  • 空值: object === null
  • null或未定义: object == null
  • 未定义:

–全局变量:`typeof variable ===’undefined’`
–局部变量:`variable === undefined`
–属性:`object.prop === undefined`
–以上任一项:`_.isUndefined(object) `

在已经使用Backbone或Underscore的任何地方,建议您在jQuery上使用Underscore.js的类型检查方法。

引号

对字符串文字使用单引号:

var myStr = 'strings should be contained in single quotes';

当字符串包含单引号时,需要使用反斜杠(\)对其进行转义:

// Escape single quotes within strings:
'Note the backslash before the \'single quotes\'';

switch语句

个案例,或者default可以利用直通逻辑(案例)时。

使用switch语句时:

  • break除以外的每种情况都使用a default。当允许语句“掉线”时,请明确指出。
  • 缩进case语句中的一个选项卡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();
}

不建议在switch语句中返回值:使用case块设置值,然后return在末尾使用这些值。

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中创建数组应该使用简写[]构造函数而不是new 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['key-with-hyphens'];

迭代

使用循环遍历大型集合时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的collection和array方法。这些功能(包括_.each_.map_.reduce)允许对大型数据集进行有效的可读转换。

Underscore还允许与常规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 );
 
<pre><code>// Do stuff to $element
</code></pre>
 
} );

切勿使用jQuery遍历原始数据或原始JavaScript对象。

JSHint

JSHint是一种自动化的代码质量工具,旨在捕获JavaScript代码中的错误。JSHint在WordPress开发中用于快速验证补丁程序是否未在前端引入任何逻辑或语法错误。

安装并运行JSHint

JSHint使用称为Grunt的工具运行。JSHint和Grunt都是用Node.js编写的程序。package.jsonWordPress开发代码随附的配置文件允许您安装和配置这些工具。

要安装Node.js,请单击Node.js网站上的“安装”链接。将为您的操作系统下载正确的安装文件。请按照操作系统的安装步骤安装程序。

安装Node.js之后,打开命令行窗口并导航到检出WordPress SVN信息库副本的目录(使用cd ~/directoryname。您应位于包含该package.json文件的根目录中。

接下来,npm install在命令行窗口中键入。这将下载并安装WordPress开发中使用的所有Node软件包。

现在,您应该能够键入npm run grunt jshint以让Grunt检查所有WordPress JavaScript文件是否存在语法和逻辑错误。要仅检查核心代码,请输入npm run grunt jshint:core; 要仅检查单元测试.js文件,请输入npm run grunt jshint:tests

JSHint设置

用于JSHint的配置选项存储在WordPress SVN存储库中的.jshintrctitle =“ svn trunk中的WordPress JSHint文件”中。该文件定义了JSHint在WordPress源代码中找到错误时应标记的错误。

检查单个文件

要为JSHint指定要检查的单个文件,请添加--file=filename.js到命令末尾。例如,这只会检查WordPress核心JavaScript文件中名为“ admin-bar.js”的文件:

npm run grunt jshint:core --file=admin-bar.js

这只会检查单元测试目录中的“ password-strength-meter.js”文件:

npm run grunt jshint:tests --file=password-strength-meter.js

如果您只处理一个或两个特定文件,并且不想等待JSHint每次运行时都处理每个文件,则将JSHint限制为单个文件可能很有用。

JSHint覆盖:忽略块

在某些情况下,应将文件的某些部分从JSHint中排除。例如,管理栏的脚本文件包含jQuery HoverIntent插件的简化代码-这是第三方代码,即使它是WordPress核心JavaScript文件的一部分,也不应通过JSHint传递。

要排除JSHint处理的特定文件区域,请将其包含在JSHint指令注释中:

/* jshint ignore:start <em>/
if ( typeof jQuery.fn.hoverIntent === 'undefined' ) {
    // hoverIntent r6 - Copy of wp-includes/js/hoverIntent.min.js
    (function(a){a.fn.hoverIntent=...............
}
/</em> jshint ignore:end */

 

发表评论