标签:
等级:Major
原因:==和!=在判断值相等前会判断类型是否相等。这容易因为类型不同而造成错误。比如:它会认为表达式:’\t\r\n’==0是正确的。因此,要采用===和!==替代这两个符号。
建议如下的方式:
if (var === ‘howdy‘) {
...
}
不建议如下的方式:
if (var == ‘howdy‘) {
...
}
例外:在判断函数是否为空的情况下,使用==或!=是可以的。在下边的例子中,如果foo没有被初始化,它默认的值是undefined而不是null。当然underfined更不会等于null了。因此这种情况应该使用==和!=。
if (foo == null) {
...
}
等级:Critical
原因:delete函数可以用来删除任何的对象。数组是对象,因此可以被delete操作。但是如果这样使用了,就会在数组中产生一个undefined元素,无法从下标中反应出delete操作。
从含有下标的元素中移除元素的适当方法有:
Array.prototype.splice – 从数组中移除元素
Array.prototype.pop – 从数组的尾端移除元素
Array.prototype.shift – 从数组的开始移除元素
建议如下的方式:
var myArray = [ ‘a‘, ‘b‘, ‘c‘, ‘d‘ ];
// removes 1 element from index 2
removed = myArray.splice(2, 1);
// myArray => [‘a‘, ‘b‘, ‘d‘]
console.log(myArray[2]); // outputs ‘d‘
不建议如下的方式:
var myArray = [ ‘a‘, ‘b‘, ‘c‘, ‘d‘ ];
delete myArray[2];
// Noncompliant. myArray => [‘a‘, ‘b‘, undefined, ‘d‘]
console.log(myArray[2]);
// expected value was ‘d‘ but output is ‘undefined‘
等级:Critical
原因:在JavaScript中eval是一个将字符串转换为JavaScript代码执行的函数,而arguments则是JavaScript的一个内置对象。如果两者作为变量使用就会覆盖了原先的定义。同是,在较为严格的JavaScript检测中,这样做是不会通过的。
建议如下的方式:
result = 17;
args++;
++result;
var obj = {
set p(arg) {
}
};
var result;
try {
}
catch (args) {
}
function x(arg) {
}
function args() {
}
var y = function fun() {
};
var f = new Function(‘args‘, ‘return 17;‘);
function fun() {
if (arguments.length == 0) {
// do something
}
}
不建议如下的方式:
eval = 17; // Noncompliant
arguments++; // Noncompliant
++eval; // Noncompliant
var obj = {
set p(arguments) {
}
}; // Noncompliant
var eval; // Noncompliant
try {
}
catch (arguments) {
} // Noncompliant
function x(eval) {
} // Noncompliant
function arguments() {
} // Noncompliant
var y = function eval() {
}; // Noncompliant
var f = new Function(‘arguments‘, ‘return 17;‘); // Noncompliant
function fun() {
if (arguments.length == 0) { // Compliant
// do something
}
}
等级:Critical
原因:如果for循环永远无法完成就会产生错误。即便不会产生错误,也会对以后的变量值造成无法确定的影响,因此不能够这样使用。
建议如下的方式:
for (i = 0; i < 10; i++) {
// ...
}
不建议如下的方式:
for (i = 0; i < 10; j++) { // Noncompliant
// ...
}
等级:Major
原因:"for … in"这种循环允许开发人员按照属性的名字遍历对象。不幸的是,这个属性的集合包括了对象自身和对象继承的对象的所有属性。如果程序不考虑这点就会出现错误。
因此,对于每个”for … in”循环,都应该包括一个if判断来过滤你需要的属性。
建议如下的方式:
for (name in object) {
if (object.hasOwnProperty(name)) {
doSomething(name);
}
}
不建议如下的方式:
for (name in object) {
doSomething(name); // Noncompliant
}
等级:Major
原因:大部分字符串或者数组的indexof方法的判断需要和-1而不是0作比较。因为0代表该元素存在于字符串或者数组中。因此所有的indexof(..)>0的判断都忽略的0这种情况,是一个典型的错误。
建议如下的方式:
var color = ‘blue‘;
var name = ‘ishmael‘;
var number = 123;
var arr = [color, name];
if (arr.indexOf(‘blue‘) >= 0) {
// ...
}
if (arr[0].indexOf(‘ish‘) > - 1{
// ...
}
不建议如下的方式:
var color = ‘blue‘;
var name = ‘ishmael‘;
var number = 123;
var arr = [color, name];
if (arr.indexOf(‘blue‘) > 0) { // Noncompliant
// ...
}
if (arr[0].indexOf(‘ish‘) > 0{ // Noncompliant
// ...
}
等级:Blocker
原因:NAN不等于包括自身在内的任何值。因此与NAN作比较是得不到你需要的结果的,但是这种错误有可能会出现。事实上,判断值是否等于NAN最好的方法就是和它自己作比较即NAN!==NAN,因为正常的变量都是等于自身的,如果不等于自身成立,就说明这个值是NAN。
建议如下的方式:
if (a !== a) {
console.log(‘a is not a number‘);
}
if (a === a) {
console.log(‘a is not NaN‘);
}
不建议如下的方式:
var a = NaN;
if (a === NaN) { // Noncompliant; always false
console.log(‘a is not a number‘); // this is dead code
}
if (a !== NaN) { // Noncompliant; always true
console.log(‘a is not NaN‘); // this statement is not necessarily true
}
等级:Critical
原因:new这个关键字应该在定义了构造函数的对象中使用。如果在其他地方使用就会出现错误因为没有构造方法可以供new调用。
建议如下的方式:
/**
* @constructor
*/
function MyClass() {
this.foo = ‘bar‘;
}
var someClass = function () {
this.prop = 1;
}
var obj1 = new someClass; // Compliant
var obj2 = new MyClass(); // Compliant regardless of considerJSDoc value
不建议如下的方式:
var someClass = 1;
var obj1 = new someClass; // Noncompliant;
等级:Major
原因:使用with关键字在一些较为严格的JavaScript检测中会报错。然而,这并不是最糟的,诚然使用with可以方便的访问到对象中既定的属性,但是如果属性在对象中尚未定义,则访问范围就会扩大到全局,有可能覆盖某些重名的变量。显然这种效果完全依赖于被访问的对象,并且产生的危害是不可测的,因此with不能使用。
建议如下的方式:
var x = ‘a‘;
var foo = {
y: 1
}
foo.y = 4;
foo.x = 3;
print(foo.x + ‘ ‘ + x); // shows: 3 a
不建议如下的方式:
var x = ‘a‘;
var foo = {
y: 1
}
with (foo) { // Noncompliant
y = 4; // updates foo.x
x = 3; // does NOT add a foo.x property; updates x var in outer scope
}
print(foo.x + ‘ ‘ + x); // shows: undefined 3
等级:Blocker
原因:如果for循环里的控制变量增长方向错误则会导致for循环永远无法执行完成。虽然有时候构建无限循环是故意的,比如使用while构建无限循环。但是,大部分情况下是存在错误。
建议如下的方式:
for (var i = 0; i < strings.length; i++) {
//...
}
不建议如下的方式:
for (var i = 0; i < strings.length; i--) { // Noncompliant;
//...
}
等级:Major
原因:由于有着对变量的特定解释方法,数组的构造方法是容易出错的。如果超过一个参量,数组的长度将会等于参量的数量。然而,如果使用一个参量将会产生三种可能结果:
如果这个参数是个数字并且是个正整数,则会产生一个长度等于该参数的数组;
如果这个参数是个数字但是不是个正整数,将会抛出异常;
其他情况下将会产生长度为1的数组。
建议如下的方式:
var a = [x1, x2, x3];
var a2 = [x1, x2];
var a3 = [x1];
var a4 = [];
var o = {};
var o2 = {
a: 0,
b: 1,
c: 2,
‘strange key‘: 3
};
不建议如下的方式:
var a3 = new Array(x1); // Noncompliant and variable in results
var a4 = new Array(); // Noncompliant. Results in 0-element array.
var a1 = new Array(x1, x2, x3); // Noncompliant. Results in 3-element array.
var o = new Object(); // Noncompliant
var o2 = new Object(); // Noncompliant
o2.a = 0;
o2.b = 1;
o2.c = 2;
o2[‘strange key‘] = 3;
等级:Major
原因:赋值语句在子表达式中容易产生错误,并且降低程序的可读性。像将==写成=是一种常见的错误。
建议如下的方式:
i = 42;
doSomething(i);
// or
doSomething(i == 42); // Perhaps in fact the comparison operator was expected
不建议如下的方式:
doSomething(i = 42);
例外:赋值语句可以在while循环或者关系表达式中出现。
while ((line = nextLine()) != null) {
...
} // Compliant
while (line = nextLine()) {
...
} // Compliant
if (line = nextLine()) {
...
} // Noncompliant
等级:Major
原因:重载一个对象改变了它自身的行为可能会影响到代码中的其它对象。如果不小心重载内置对象可能会对其它的代码产生灾难性的危害。这条规则检测如下内置对象是否被重载:
基本对象 - Object, Function, Boolean, Symbol, Error, EvalError, InternalError, RangeError, ReferenceError, SyntaxError, TypeError, URIError;
数据和时间- Number, Math, Date;
文本处理-String, RegExp;
各种数组- Array, Int8Array, Uint8Array, Uint8ClampedArray, Int16Array, Unit16Array, Int32Array, Uint32Array, Float32Array, Float64Array;
集合-Map, Set, WeakMap, WeakSet;
结构化数据- ArrayBuffer, DataView, JSON;
控制抽象的关键字-Promise;
反射-Reflect,Proxy;
国际化-Intl;
非标准的对象-Generator, Iterator, ParallelArray, StopIteration.
等级:Major
原因:如果一个变量在赋值后没有被使用,则会产生无用的存储。只有尽快释放它,才不会对代码造成危害。即便不产生危害,对资源也是一种浪费。因此,要保证所有定义的变量都要被用到。
建议如下的方式:
function pow(a, b) {
if (b == 0) {
return 0;
}
var x = a;
for (var i = 1, i < b, i++) {
x = x * a;
}
return x;
}
不建议如下的方式:
function pow(a, b) {
if (b == 0) {
return 0;
}
var x = a;
for (var i = 1, i < b, i++) {
x = x * a; //Dead store because the last return statement should return x instead of returning a
}
return a;
}
等级:Critical
原因:在JavaScript中你可以在调用函数时传入比函数自身要求的更多的参数,但是,要保证额外的参数能够被使用。
建议如下的方式:
function doSomething(a, b) {
compute(arguments);
}
doSomething(1, 2, 3) // Compliant
不建议如下的方式:
function say(a, b) {
print(a + ‘ ‘ + b);
}
say(‘hello‘, ‘world‘, ‘!‘); // Noncompliant; last argument is not used
等级:Major
原因:在循环内部定义函数会造成不可预料的结果,因为这样定义的函数生命周期很短,同时其中的变量值也会不断被更新。
不建议如下的方式:
var funs = [];
for (var i = 0; i < 13; i++) {
funs[i] = function () { // Non-Compliant
return i;
};
}
print(funs[0] ()); // 13 instead of 0
print(funs[1] ()); // 13 instead of 1
print(funs[2] ()); // 13 instead of 2
print(funs[3] ()); // 13 instead of 3
...
等级:Major
原因:这条规则检测在同一个作用域内是否有同名的函数。事实上,很有可能产生这种现象,但是JavaScript引擎只会执行最后一次声明的那个函数。这种重复声明函数的代码通常会带来bug并且会让代码很乱。
建议如下的方式:
fun(); // prints "foo"
function fun() {
print(‘foo‘);
}
fun(); // prints "foo"
或者是:
fun(); // prints "foo"
function fun() {
print(‘foo‘);
}
fun(); // prints "foo"
function printBar() {
print(‘bar‘);
}
fun(); // prints "foo"
不建议如下的方式:
fun(); // prints "bar"
// first declaration of the function
function fun() {
print(‘foo‘);
}
fun(); // prints "bar"
// redeclaration of the "fun" function: this definition overrides the previous one
function fun() {
print(‘bar‘);
}
fun(); // prints "bar"
等级:Major
原因:这种注释的风格不是JavaScript规范的一部分所以不能够使用
建议如下的方式:
// Compliant
/* Compliant */
不建议如下的方式:
<!-- Noncompliant -->
等级:Critical
原因:
使用相同值的二元运算符往往会造成错误。这种情况的逻辑操作符,要么是个粘贴拷贝的错误,要么就是在浪费代码,需要修改。如果出现在布尔表达式中,结果就是可以确定的,没有意义。
建议如下的方式:
doZ();
if (a == b) {
doX();
}
if (a == b) {
doW();
}
var j = 1;
var k = 0;
不建议如下的方式:
if (a == a) { // always true
doZ();
}
if (a != a) { // always false
doY();
}
if (a == b && a == b) { // if the first one is true, the second one is too
doX();
}
if (a == b || a == b) { // if the first one is true, the second one is too
doW();
}
var j = 5 / 5; //always 1
var k = 5 - 5; //always 0
例外:在测试值是否是NAN情况下是可以使用的,因为只有NAN不等于自身。
f(f !== f) { // test for NaN value
console.log(‘f is NaN‘);
}
var i = 1 << 1; // Compliant
var j = a << a; // Noncompliant
不建议如下的方式:
for (var i = 0; i < length; i++) {
} // Empty on purpose or missing piece of code ?
例外:如果代码块中嵌套着注释,则这个代码块可以为空。
建议如下的方式:
var data = {
‘key‘: ‘value‘,
‘1‘: ‘value‘,
‘key2‘: ‘value‘,
‘key3‘: ‘value‘,
key4: ‘value‘,
\u006bey5: ‘value‘,
‘\u006bey6‘: ‘value‘,
‘\x6bey7‘: ‘value‘,
1b: ‘value‘
}
不建议如下的方式:
var data = {
‘key‘: ‘value‘,
‘1‘: ‘value‘,
‘key‘: ‘value‘, // Noncompliant - duplicate of "key"
‘key‘: ‘value‘, // Noncompliant - duplicate of "key"
key: ‘value‘, // Noncompliant - duplicate of "key"
key: ‘value‘, // Noncompliant - duplicate of "key"
‘key‘: ‘value‘, // Noncompliant - duplicate of "key"
‘key‘: ‘value‘, // Noncompliant - duplicate of "key"
1: ‘value‘ // Noncompliant - duplicate of "1"
}
建议如下的方式:
if (param == 1)
openWindow();
else if (param == 2)
closeWindow();
else if (param == 3)
moveWindowToTheBackground();
switch (i) {
case 1:
//...
break;
case 3:
//...
break;
default:
// ...
break;
}
不建议如下的方式:
if (param == 1)
openWindow();
else if (param == 2)
closeWindow();
else if (param == 1) // Noncompliant
moveWindowToTheBackground();
switch (i) {
case 1:
//...
break;
case 3:
//...
break;
case 1: // Noncompliant
//...
break;
default:
// ...
break;
}
建议如下的方式:
for (var i = 1; i <= 10; i += 2) // Compliant
{
//...
}
不建议如下的方式:
for (var i = 1; i != 10; i += 2) // Noncompliant. Infinite; i goes from 9 straight to 11.
{
//...
}
例外:如果测试的是null则可以使用==和!=,比如:
for (inti = 0; arr[i] != null; i++) {
// ...
}
for (inti = 0; (item = arr[i]) != null; i++) {
// ...
}
建议如下的方式:
// Testing whether a selection contains elements.
if ($(‘div.foo‘).length > 0) {
// this code only runs if elements were found
// ...
}
不建议如下的方式:
if ($(‘div.foo‘)) { // Noncompliant
// this code always runs, even when the selector didn‘t match any elements
// ...
}
建议如下的方式:
var person = {
// ...
set name(name) {
this.name = name;
}
}
不建议如下的方式:
var person = {
// ...
set name(name) {
this.name = name;
return 42; // Noncompliant
}
}
建议如下的方式:
if (str != null && str.length == 0) {
console.log(‘String is empty‘);
}
if (str != undefined && str.length == 0) {
console.log(‘String is empty‘);
}
if (str == null || str.length > 0) {
console.log(‘String is not empty‘);
}
if (str == undefined || str.length > 0) {
console.log(‘String is not empty‘);
}
不建议如下的方式:
if (str == null && str.length == 0) {
console.log(‘String is empty‘);
}
if (str == undefined && str.length == 0) {
console.log(‘String is empty‘);
}
if (str != null || str.length > 0) {
console.log(‘String is not empty‘);
}
if (str != undefined || str.length > 0) {
console.log(‘String is not empty‘);
}
好的方法:
parseInt("010", 10);
不建议如下的方式:
parseInt("010"); // Noncompliant; pre-2013 browsers may return 8
建议如下的方式:
switch (i) {
case 1:
case 3:
doSomething();
break;
case 2:
doSomethingDifferent();
break;
default:
doTheRest();
}
if ((a >= 0 && a < 10) || (a >= 20 && a < 50)) {
doTheThing();
else if (a >= 10 && a < 20) {
doTheOtherThing();
}
else {
doTheRest();
}
或者是:
switch (i) {
case 1:
doSomething();
break;
case 2:
doSomethingDifferent();
break;
case 3:
doThirdThing();
break;
default:
doTheRest();
}
if (a >= 0 && a < 10) {
doTheThing();
else if (a >= 10 && a < 20) {
doTheOtherThing();
}
else if (a >= 20 && a < 50) {
doTheThirdThing();
}
else {
doTheRest();
}
不建议如下的方式:
switch (i) {
case 1:
doSomething();
break;
case 2:
doSomethingDifferent();
break;
case 3: // Noncompliant; duplicates case 1‘s implementation
doSomething();
break;
default:
doTheRest();
}
if (a >= 0 && a < 10) {
doTheThing();
else if (a >= 10 && a < 20) {
doTheOtherThing();
}
else if (a >= 20 && a < 50) {
doTheThing(); // Noncompliant; duplicates first condition
}
else {
doTheRest();
}
CompliantSolution:
switch (i) {
case 1:
case 3:
doSomething();
break;
case 2:
doSomethingDifferent();
break;
default:
doTheRest();
}
if ((a >= 0 && a < 10) || (a >= 20 && a < 50)) {
doTheThing();
else if (a >= 10 && a < 20) {
doTheOtherThing();
}
else {
doTheRest();
}
建议如下的方式:
var i = 0;
i++;
不建议如下的方式:
var i = 0;
i = i++; // Noncompliant; i is still zero
建议如下的方式:
var a = ‘foo‘;
function otherName() {
}
console.log(a);
function myFunc(arg) {
var newName = ‘event‘;
}
fun(); // prints "foo"
function fun() {
print(‘foo‘);
}
fun(); // prints "foo"
function printBar() {
print(‘bar‘);
}
printBar(); // prints "bar"
不建议如下的方式:
var a = ‘foo‘;
function a() {
} // Noncompliant
console.log(a); // prints "foo"
function myFunc(arg) {
var arg = ‘event‘; // Noncompliant, argument value is lost
}
fun(); // prints "bar"
function fun() {
console.log(‘foo‘);
}
fun(); // prints "bar"
function fun() { // Noncompliant
console.log(‘bar‘);
}
fun(); // prints "bar"
建议如下的方式:
var a = ‘foo‘;
var b = ‘bar‘;
function f(e) {
var g = ‘event‘;
}
不建议如下的方式:
var a = ‘foo‘;
var a = ‘bar‘; // Non-Compliant
function f(e) {
var e = ‘event‘; // Non-Compliant
}
建议如下的方式:
function setName(name) {
this.name = name;
}
不建议如下的方式:
function setName(name) {
name = name;
}
建议如下的方式:
for (i = 0; i < 10; i++) {
if (i != 5) { /* Compliant */
alert(‘i = ‘ + i);
}
}
不建议如下的方式:
for (i = 0; i < 10; i++) {
if (i == 5) {
continue; /* Non-Compliant */
}
alert(‘i = ‘ + i);
}
建议如下的方式:
if (variable == 0) {
doSomething();
} else {
doSomethingElse();
}
不建议如下的方式:
switch (variable) {
case 0:
doSomething();
break;
default:
doSomethingElse();
break;
}
建议如下的方式:
a += 2;
i = a + b;
不建议如下的方式:
i = a += 2, a + b; // What‘s the value of i ?
例外:在for循环中的控制部分是可以使用逗号分割表达式的。
for(i = 0, j = 5; i < 6; i++, j++) { ... }
4. 代码段不应该被注释掉
建议如下的方式:
function doSomething(b) {
return compute(b);
}
不建议如下的方式:
function doSomething(a, b) { // "a" is unused
return compute(b);
}
例外:当函数存在返回值时,有些变量可能需要作为某些函数的标志。例如:
$([‘first‘,‘last‘]).each(function (i, value) {
computeSomethingWithValue(value);
});
var myFirsCallBackFunction = function (p1, p2, p3, p4) { //unused p2 is not reported but p4 is
return p1 + p3;
}
var mySecondCallBackFunction = function (p1, p2, p3, p4) { //unused p1, p2 and p3 are not reported
return p4;
}
var myThirdCallBackFunction = function (p1, p2, p3, p4) { //unused p1 is not reported but p3 and p4 are
return p2;
}
原因:以下的单词是JavaScript保留字,用于JavaScript以后的拓展,不能作为标识符使用。
await
class
const
enum
exports
extends
implements
import
interface
let
package
private
protected
public
static
super
yield
建议如下的方式:
var elements = document.getElementsByName(‘foo‘); // Compliant
不建议如下的方式:
var package = document.getElementsByName(‘foo‘); // Noncompliant
var someData = { package: true }; // Compliant, as it is not used as an identifier here
原因:即便是合法的,这样做也会大大降低代码可读性,严重时,会造成意想不到的错误。
建议如下的方式:
Case1
switch (day) {
case MONDAY:
case TUESDAY:
case WEDNESDAY:
doSomething();
break;
...
}
Case2
switch (day) {
case MONDAY:
break;
case TUESDAY:
compute(args); // put the content of the labelled "for" statement in a dedicated method
break;
/* ... */
}
不建议如下的方式:
Case1,
The code is syntactically correct but the behavior is not the expecte done
switch (day) {
case MONDAY:
case TUESDAY:
WEDNESDAY: // instead of "case WEDNESDAY"
doSomething();
break;
...
}
Case2,the code is correct and behaves as expected but is hardly readable
switch (day) {
case MONDAY:
break;
case TUESDAY:
foo: for (i = 0; i < X; i++) {
/* ... */
break foo; // this break statement doesn‘t relate to the nesting case TUESDAY
/* ... */
}
break;
/* ... */
}
原因:undefined是一个属性尚未创建的标志。如果将它赋值给已经存在的属性,你将无法区分变量是否创建。更好的方式是你可以使用null代替。
建议如下的方式:
var myObject = {
};
// ...
myObject.fname = null;
// ...
if (myObject.lname == undefined) {
// property not yet created
}
if (myObject.fname == undefined) {
// no real way of knowing the true state of myObject.fname
}
不建议如下的方式:
var myObject = {
};
// ...
myObject.fname = undefined; // Noncompliant
// ...
if (myObject.lname == undefined) {
// property not yet created
}
if (myObject.fname == undefined) {
// no real way of knowing the true state of myObject.fname
}
原因:JavaScript没有integer类型,但是它有安位操作符<<, >>, >>>, ~, &,I。这种操作会首先将float类型转换为integer类型,然后再转换回来,并不能像C那样高效。更何况,支持这种操作的浏览器也很少。
建议如下的方式:
if (a && b) {
...
}
var oppositeSigns = false;
if ((x < 0 && y > 0) || (x > 0 && y < 0)) {
oppositeSigns = true;
}
不建议如下的方式:
if (a & b) {
...
} // Noncompliant; & used in error
var oppositeSigns = ((x ^ y) < 0); // Noncompliant; there‘s a clearer way to test for this
原因:有些工程师喜欢单独调用构造方法而不将值赋值给变量。这是有百害无一利的做法,因为这样构造的对象就无法在其它地方使用了。
建议如下的方式:
var something = new MyConstructor(); // Compliant
不建议如下的方式:
new MyConstructor(); // Non-Compliant
原因:虽然没有语法的错误,但是不使用大括号会降低代码的可读性。还有可能造成逻辑上的错误。
建议如下的方式:
if (condition) {
executeSomething();
checkSomething();
}
不建议如下的方式:
// the two statements seems to be attached to the if statement, but that is only true for the first one:
if (condition)
executeSomething();
checkSomething();
原因:函数的参数名应该不一样以防操作产生混乱。实际上,如果存在相同的参数名,最后一个参数将会覆盖前边相同的参数。这种做法是没有意义的,降低了可读性和可维护性。
建议如下的方式:
function compute(a, b, c) { // Compliant
}
不建议如下的方式:
function compute(a, a, c) { // Noncompliant
}
原因:因为“;”一行的结束符在JavaScript中不是必须的,如果函数调用的参数在新的一行开始就会让代码可读性大大降低。可能会导致错误和以后维护的问题。
建议如下的方式:
// define a function
Either
var fn = function () {
//...
}; // <-- semicolon added
// then execute some code inside a closure
(function () {
//...
}) ();
Or
var fn = function () {
//...
}(function () { // <-- start function call arguments on same line
//...
}) ();
不建议如下的方式:
var fn = function () {
//...
}(function () { // Noncompliant
//...
}) ();
原因:开发人员有可能使用undefined作为变量,但是这个关键字是区别变量是否创建的标志。如果被覆盖,你将无法区别变量是否存在。
建议如下的方式:
function foo() {
var bob = 1; // anything is better than naming it ‘undefined‘
if (nonExistantVar == undefined) {
// ...
}
}
不建议如下的方式:
function foo() {
var undefined = 1; // Noncompliant
if (nonExistantVar == undefined) { // this logic doesn‘t work now
// ...
}
}
10. 八进制不能被使用
原因:尽管JavaScript是完全支持八进制的,但是大部分开发人员不能熟练的使用八进制。他们可能会将八进制当做十进制数字来处理。
建议如下的方式:
var myNumber = 8;
不建议如下的方式:
var myNumber = 010; // myNumber will hold 8, not 10 - was this really expected?
原因:在任何代码块中都可以识别label,但是只能在”while”,”do”和”for”使用label。在其他结构中使用label都会使结构混乱,代码难以理解。
建议如下的方式:
myLabel: for (i = 0; i < 10; i++) { // Compliant
print(‘Loop‘);
break myLabel;
}
不建议如下的方式:
myLabel: if (i % 2 == 0) { // Noncompliant
if (i == 12) {
print(‘12‘);
break myLabel;
}
print(‘Odd number, but not 12‘);
}
12. 源文件中不能有重复的模块
原因:如果条件中没有break,那么程序就会继续往下执行。虽然有时候这是开发人员有意设置的,但是更大可能的是代码错误。
建议如下的方式:
switch (myVariable) {
case 1:
foo();
break;
case 2:
doSomething();
break;
default:
doSomethingElse();
break;
}
不建议如下的方式:
switch (myVariable) {
case 1:
foo();
break;
case 2: // Both ‘doSomething()‘ and ‘doSomethingElse()‘ will be executed. Is it on purpose ?
doSomething();
default:
doSomethingElse();
break;
}
例外:以下情况,该规则认为是合理的:
switch (myVariable) {
case 0: // Empty case used to specify the same behavior for a group of cases.
case 1:
doSomething();
break;
case 2: // Use of return statement
return;
case 3: // Use of throw statement
throw new IllegalStateException();
case 4: // Use of continue statement
continue;
default: // For the last case, use of break statement is optional
doSomethingElse();
}
14. 不能在对象外使用THIS
原因:如果在对象外使用this,它将指代全局的对象window。显而易见,这样将会造成难以控制的错误。
建议如下的方式:
foo = 1;
console.log(foo);
function MyObj() {
this.foo = 1;
}
MyObj.func1 = function () {
if (this.foo == 1) {
// ...
}
}
不建议如下的方式:
this.foo = 1; // Noncompliant
console.log(this.foo); // Noncompliant
function MyObj() {
this.foo = 1; // Compliant
}
MyObj.func1 = function () {
if (this.foo == 1) { // Compliant
// ...
}
}
原因:不能在一个作用域内使用相同的名子声明变量或函数。这不但会降低代码可读性,而且会导致不必要的错误。
建议如下的方式:
var fun = function fun() {
}
* 不建议如下的方式:
var fun;
function fun() {
}
原因:JavaScript变量的作用域很难掌握准确。如果存在全局变量会让这种情况变得更糟。
建议如下的方式:
function f() {
var i = 1;
for (var j = 0; j < array.length; j++) {
// ...
}
}
不建议如下的方式:
function f() {
i = 1; // Noncompliant; i is global
for (j = 0; j < array.length; j++) { // Noncompliant; j is global now too
// ...
}
}
原因:JavaScript困扰开发人员的最大问题就是作用域。主要的原因是虽然JavaScript看起来像是类似C语言的。但是实际并不是。C语言家族有明显的的作用域标志,它们是通过块来控制的,比如if块,你可以在里边建立新的变量,这样并不会影响块以外的作用域,而JavaScript却不可以。为了尽量避免作用域的困扰,在变量使用前一定要先声明。
建议如下的方式:
var x = 1;
function fun() {
print(x);
if (something) {
x = 42;
}
}
fun(); // Print "1"
不建议如下的方式:
var x = 1;
function fun() {
alert(x); // Noncompliant as x is declared later in the same scope
if (something) {
var x = 42; // Declaration in function scope (not block scope!) shadowsglobal variable
}
}
fun(); // Unexpectedly alerts "undefined" instead of "1"
原因:覆盖一个在外域的变量会降低代码可读性和可维护性。更有甚者,会引入错误。
建议如下的方式:
show: function (point, element) {
if (!this.drops.length) return;
var drop,
affected = [
];
this.drops.each(function (aDrop) {
if (Droppables.isAffected(point, element, aDrop))
affected.push(aDrop);
});
不建议如下的方式:
show: function (point, element) {
if (!this.drops.length) return;
var drop,
affected = [
];
this.drops.each(function (drop) { // Non-Compliant; defines a new ‘drop‘ parameter
if (Droppables.isAffected(point, element, drop))
affected.push(drop);
});
原因:使用基本类型包装的对象定义变量是没有意义的。
建议如下的方式:
var x = false;
if (x) {
alert(‘hi‘);
}
不建议如下的方式:
var x = new Boolean(false);
if (x) {
alert(‘hi‘); // Shows ‘hi‘.
}
安全相关——7条
原因:在开发的过程中,会使用alert()进行debug,但是发布的应用中,这种弹出方式可能会给攻击者泄露敏感信息。
不建议如下使用方式:
if (unexpectedCondition)
{
alert(‘Unexpected Condition‘);
}
2. 代码不应该动态注入执行,以防止出现EVAL注入问题
原因:eval是在运行的时候执行任意代码的函数,一般来说,用eval函数是很危险的,因为它可以执行任意的代码,如果经过必须使用该函数,则要特别注意该函数处理的任何用户输入数据。
不建议如下使用方式:
eval(code_to_be_dynamically_executed)
原因:Debug信息在开发过程中很有用,但是在发布的版本中,特别是客户端保留Debug信息,会造成敏感信息泄露,使浏览器运行缓慢,甚至是浏览器进程崩溃错误。
不建议如下使用方式:
console.log(password_entered);
原因:HTML5引入了一个在跨域页面之间通讯的方法,为了降低向目标域以及未知域中传递敏感消息的危险,每次调用Window.postmessage方法的时候都须多加注意,不应该使用通配符*。
不建议如下的使用方式:
var myWindow = document.getElementById(‘myIFrame‘).contentWindow;
myWindow.postMessage(message, ‘*‘); // Noncompliant; how do you know what you loaded in ‘myIFrame‘ is still there?
原因:Debugger语句可以在程序的任何地方声明来暂停程序执行。利用debugger语句就像在代码中加了一个断点一样。在发布的代码中,任何debugger语句都必须被移除。
不建议如下的使用方式:
for (i = 1; i < 5; i++) {
// Print i to the Output window.
Debug.write(‘loop index is ‘ + i);
// Wait for user to resume.
debugger;
}
建议如下的使用方式:
for (i = 1; i < 5; i++) {
// Print i to the Output window.
Debug.write(‘loop index is ‘ + i);
}
不建议如下的使用方式:
if (true) { // Noncompliant
doSomething();
}...if (false) { // Noncompliant
doSomethingElse();
}
if (!options || options === true) {
doThirdThing();
}
// Noncompliant; always true
建议的使用方式:
doSomething();
doThirdThing();
原因:本地数据库标准在W3C标准中已经不推荐使用,此外,使用本地数据库也会产生相应的安全问题。
不建议如下的使用方式:
var db = window.openDatabase(‘myDb‘, ‘1.0‘, ‘Personal secrets stored here‘, 2 * 1024 * 1024); //Noncompliant
1. 在靠类型选择元素的时候应该利用“[TYPE=...]”
原因:在JQuery中,和type="<element_type>"都可以用来选择元素,但是type="<element_type>"因为利用了本地的DOM querySelectorAll()方法,所以更快一些。
不建议如下的方式:
var input = $( ‘form input:radio‘ ); // Noncompliant
建议如下的方式:
var input = $( ‘form input[type=radio]‘ ); // Compliant
不建议如下的方式:
var $productIds = $(‘#products div.id‘); // Noncompliant - a nested query for Sizzle selector engine
建议如下的方式:
var $productIds = $(‘#products‘).find(‘div.id‘); // Compliant - #products is already selected by document.getElementById() so only div.id needs to go through Sizzle selector engine
jQuery不会替你缓存元素,如果你选择了你可能还会用到的变量,你应该将选择结果保存在变量中。
不推荐如下的方式:
$( ‘p‘ ).hide();
$( ‘p‘ ).show();
推荐如下的方式:
var paragraph = $( ‘p‘ );
paragraph.hide();
paragraph.show();
例外情况:DOM变化时,保存的selections没有更新, 如下:
var paragraph = $(‘p‘);
// ...
paragraph = $(‘p‘);
触发本条规则的重复值为2
5. 通配选择器不应该被使用
不建议如下的方式:
$( ‘.buttons > *‘ ); // Noncompliant; extremely expensive
建议如下的方式:
$( ‘.buttons‘ ).children(); // Compliant
1. 注释不应该写在每一行的最后面
原因:关于单行的注释,不建议将注释写在该行代码的最后,为了增加程序的可读性,建议将注释写在代码的前一个空行上。
不建议如下的方式:
var a1 = b + c; // This is a trailing comment that can be very very long
建议如下的方式:
// This very long comment is better placed before the line of code
var a2 = b + c;
当注释只有一个单词的时候,允许注释写在代码的后面,这是一种特例
doSomething(); //FIXME
原因:虽然在JavaScript中,在声明后面添加“;”不是强制性的,但是省略“;”是一种不值得提倡的做法,在有些情况下可能会引起意想不到的结果。
不建议如下的方式:
function fun() {
return
// Noncompliant. ‘;‘ implicitly inserted at end of line
5
// Noncompliant. ‘;‘ implicitly inserted at end of line
}
print(fun()); // prints "undefined", not "5"
建议如下的方式:
function fun() {
return 5;
}
print(fun());
原因:这条规则会使得在利用一些工具,例如Git的时候配合的更好。
建议如下的使用方式:
class Test {
}
\\newline at end of file
不建议如下的方式:
function DoSomething(){...}
建议如下的方式:
function doSomething(){...}
默认的规范正则表达式为:^[a-z][a-zA-Z0-9]*$
原因:和第4点相同,JQuery的变量命名也需要符合一定的规范。
默认的命名检查正则表达式为:^\$[a-z][a-zA-Z0-9]*$
7. 一行代码结束后不应该额外的空格
原因:结尾的空格是无用的,且不应该保留在代码中,在比较不同版本的相同文件时,末尾的空格可能会造成影响。
不建议如下的方式:
// The following string will error if there is a whitespace after ‘\‘
var str = "Hello \
World";
原因:将字符串用单引号声明而非双引号。
不建议如下的方式:
var firstParameter = "something";
建议如下的方式:
var firstParameter = ‘something‘;
原因:为了便于阅读,不要将许多statement放在一行
不建议如下的方式:
if(someCondition) doSomething();
建议如下的方式:
if(someCondition) {
doSomething();
}
例外情况:遇到只包含一个statement的匿名函数时例外,如下:
onEvent(function() { doSomething(); }); // Compliant
onEvent(function(p) { doSomething(); return p %2 ;}); // Noncompliant
浏览器兼容性问题----2条
原因:某些浏览器不支持命名函数表达式,比如IE8
不建议如下的方式:
f = function fun(){}; // Non-Compliant; named function expression
建议如下的方式:
fun = function(){}; // Compliant; function expression
例外情况:ECMAScript6的generator function不被包含在内,如下:
function* f() {} // Compliant; generator function.
原因:虽然大多数script引擎支持在块中声明函数,但是它不是ECMAScript5以及其之前版本的标准,且各个浏览器的处理方式是不一致的。如果你的目标浏览器不支持ECMAScript6,那么在块中利用变量定义一个函数表达式。
不建议如下的使用方式:
if (x) {
function foo() {}
}
建议如下的方式:
if (x) {
var foo = function() {}
}
原因:嵌套太深的代码难以阅读,重构以及维护
不建议如下的方式:
if (condition1) { // Compliant - depth = 1
/* ... */
if (condition2) { // Compliant - depth = 2
/* ... */
for (inti = 0; i < 10; i++) { // Compliant - depth = 3, not exceeding the limit
/* ... */
if (condition4) { // Non-Compliant - depth = 4
if (condition5) { // Depth = 5, exceeding the limit, but issues are only reported on depth = 4
/* ... */
}
return;
}
}
}
}
默认触发问题报告的嵌套深度为3.
原因:表达式的复杂程度是由&&,||,以及?,ifTrue:ifFalse操作符定义的,一个表达式不应该有超过三个的操作符,以增加表达式的可读性。
默认触发值为3.
例外情况:
这个函数忽略了Immediately Invoked Function Expressions (IIFE),函数被创建或者调用时没有分配名字。如下:
(function () { // Ignored by this rule
function open() { // Classic function declaration; not ignored
// ...
}
function read() {
// ...
}
function readlines() {
// ...
}
}) ();
触发此条件的函数的最大行为300
不建议如下的方式:
function doSomething(param1, param2, param3, param4, param5) {
...
}
建议如下的方式:
public void doSomething(intparam1, intparam2, intparam3, Stringparam4) {
...
}
触发该问题的参数临界值为7,建议用数组或对象代替多个参数。
不建议如下的方式:
for (var i = 1; i <= 10; i++) { // Noncompliant - 2 continue - one might be tempted to add some logic in between
if (i % 2 == 0) {
continue;
}
if (i % 3 == 0) {
continue;
}
alert(‘i = ‘ + i);
}
简单说明如下:
return 3; // Compliant
return (x); // Non-Compliant
return (x + 1); // Non-Compliant
intx = (y / 2 + 1); // Non-Compliant
inty = (4 + X) * y; // Compliant
原因:如果一个本地的变量被声明而没有被使用,它应该被移除,这样会提高代码维护的效率。
不建议如下的方式:
function numberOfMinutes(hours) {
var seconds = 0; // seconds is never used
return hours * 60;
}
建议如下的方式:
function numberOfMinutes(hours) {
return hours * 60;
}
原因:这两个函数在最新的Javascript版本中不建议被使用,可能会对优化造成影响。在ECMAScript5中,这两个函数在strict模式下都被禁止使用。
不建议如下的方式:
function whoCalled() {
if (arguments.caller == null) //Noncompliant
console.log(‘I was called from the global scope.‘);
else
console.log(arguments.caller + ‘ called me!‘); // Noncompliant
console.log(whoCalled.caller); // Noncompliant
console.log(whoCalled.arguments); // Noncompliant
}
1. 多行的STRING变量不应该使用\
原因:虽然不同的script引擎可以识别多行的string变量(用\方式),但是这种形式没有被规定在ECMAScript标准中。
不建议如下的方式:
var myString = ‘A rather long string of English text, an error message actually that just keeps going and going -- an error message to make the Energizer bunny blush (right through those Schwarzenegger shades)! Where was I? Oh yes, you have got an error and all the extraneous whitespace is just gravy. Have a nice day.‘; // Noncompliant
建议如下的方式:
var myString = ‘A rather long string of English text, an error message ‘ +
‘actually that just keeps going and going -- an error ‘ +
‘message to make the Energizer bunny blush (right through ‘ +
‘those Schwarzenegger shades)! Where was I? Oh yes, ‘ +
‘you have got an error and all the extraneous whitespace is ‘ +
‘just gravy. Have a nice day.‘;
原因:当for循环中之定义了状态时应该用while循环代替
不建议如下的方式:
for (; condition; ) { /*...*/
}
建议如下的方式:
while (condition) { /*...*/
}
3. 可折叠的IF语句应该被合并
原因:合并可折叠的if语句,从而增加代码的可读性
不建议如下的方式:
if (x != undefined) {
if (x === 2) {
// ...
}
}
建议如下的方式:
if (x != undefined && x === 2) {
// ...
}
不建议如下的方式:
if (booleanVariable == true) { /* ... */
}
if (booleanVariable != true) { /* ... */
}
if (booleanVariable || false) { /* ... */
}
doSomething(!false);
建议如下的方式:
if (booleanVariable) { /* ... */
}
if (!booleanVariable) { /* ... */
}
if (booleanVariable) { /* ... */
}
doSomething(true);
例外情况:如果文字的布尔值出现在恒等运算符中则被忽略,如下:
(=== and !==)
5. 返回BOOLEAN类型的表达式不应该被放在IF-THEN-ELSE语句中
不建议如下的方式:
if (expression) {
return true;
} else {
return false;
}
建议如下的方式:
return expression;
return !!expression;
不建议被使用的方式:
var settings = {
‘foo‘: oof,
‘bar‘: rab, // Noncompliant - trailing comma
};
建议的方式:
var settings = {
‘foo‘: oof,
‘bar‘: rab
};
1. ”TODO”标签不能出现
原因:该标签是一个标记开发人员将来将要在此处实现某些代码的标志。有时开发人员会忘记这事,需要对开发人员作出提醒。
不建议如下的方式:
function doSomething() {
// TODO
}
原因:FIXME是开发人员对出现错误的代码进行的标记,有时开发人员可能会忘记,需要进行一下提醒。
function divide(numerator, denominator) {
return numerator / denominator; // FIXME denominator value might be 0
}
标签:
原文地址:http://www.cnblogs.com/Spring-Rain/p/5514827.html