【知识总结】交了这么多年JavaScript学费,你掌握了多少(第一期)
应该使用“ === ”和“!==”代替“ ==”和“!=”
在==
与!=
比较值之前,执行类型强制。这很糟糕,因为它可能掩盖类型错误。
例如,它的计算结果' \t\r\n' == 0
返回为true
。
“ [type = ...]”应用于按类型选择元素
虽然:<element_type>
和[type="<element_type>"]
都可以在jQuery中用于按元素类型选择元素,但[type="<element_type>"]
速度要快得多,因为它可以利用querySelectorAll()
现代浏览器中的本机DOM 方法。
使用以下选择器时,此规则会引起问题:
- :checkbox
- :file
- :image
- :password
- :radio
- :reset
- :text
不兼容的代码示例:
var input = $(“ form input:radio”); //不符合规定
兼容解决方案:
var input = $(“ form input [type = radio]”); //符合
不推荐使用,该规则已弃用,最终将被删除。
不应使用“ alert(...)”
alert(...)
以及confirm(...)
和prompt(...)
可以在开发过程中调试非常有用,但在生产模式这种弹出的可能暴露敏感信息给攻击者,不应该被显示。
不兼容的代码示例:
if(unexpectedCondition){
alert(“意外情况”);
}
"arguments" 不应直接访问
JavaScript的神奇之处在于,你可以将参数传递给未声明参数的函数,另一方面,也可以在no-args内使用这些传入的参数function。
如果你不想显式命名参数,请使用...
语法指定期望可变数量的参数。然后在函数内部,你将要处理一类数组,而不是类似数组的结构。
不兼容的代码示例:
function concatenate() {
let args = Array.prototype.slice.call(arguments); // Noncompliant
return args.join(', ');
}
function doSomething(isTrue) {
var args = Array.prototype.slice.call(arguments, 1); // Noncompliant
if (!isTrue) {
for (var arg of args) {
...
}
}
兼容解决方案:
function concatenate(...args) {
return args.join(', ');
}
function doSomething(isTrue, ...values) {
if (!isTrue) {
for (var value of values) {
...
}
}
}
不应使用“ arguments.caller”和“ arguments.callee”
arguments.caller
和arguments.callee做
了不少优化,不可能让他们在JavaScript中的最新版本中不建议使用。实际上,strict根据文档,EcmaScript 5禁止在模式下同时使用两者:
严格模式功能的参数对象定义了名为“ caller”
和“ callee”
的不可配置的访问器属性,这些属性在访问时引发TypeError异常
。
不兼容的代码示例:
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
“ await”不应冗余使用
一个async函数总是包裹在一个返回值Promise,return await的使用是多余的。
不兼容的代码示例:
async function foo() {
// ...
}
async function bar() {
// ...
return await foo(); // Noncompliant
}
兼容解决方案:
async function foo() {
// ...
}
async function bar() {
// ...
return foo();
}
“ catch”子句的作用不仅仅在于重新抛出
一个catch子句只会重新抛出捕获到的异常,其效果与完全省略catch并让它自动弹出的效果相同,但会产生更多的代码,而且还会增加维护人员的工作量。
此类子句应被消除或使用适当的逻辑填充。
不兼容的代码示例:
try {
doSomething();
} catch (ex) { // Noncompliant
throw ex;
}
兼容解决方案:
try {
doSomething();
} catch (ex) {
console.err(ex);
throw ex;
}
不应使用“continue”
continue是非结构化的控制流语句。它使代码的可测试性,可读性和可维护性降低。if应该使用结构化的控制流语句,例如:
不兼容的代码示例:
for (i = 0; i < 10; i++) {
if (i == 5) {
continue; /* Noncompliant */
}
alert("i = " + i);
}
兼容解决方案:
for (i = 0; i < 10; i++) {
if (i != 5) { /* Compliant */
alert("i = " + i);
}
}
“default”子句应写在最后
switch可以default出于各种原因而包含一个子句:处理意外值,以表明所有情况都经过适当考虑。
出于可读性考虑,为了帮助开发人员快速找到switch语句的默认行为,建议将default子句放在 语句的末尾switch。如果default子句不是的第一个或最后一个switch案例,则此规则会引起问题。
不兼容的代码示例:
switch (param) {
case 0:
doSomething();
break;
default: // default clause should be the first or last one
error();
break;
case 1:
doSomethingElse();
break;
}
兼容解决方案:
switch (param) {
case 0:
doSomething();
break;
case 1:
doSomethingElse();
break;
default:
error();
break;
}
“delete”应仅与对象属性一起使用
delete运算符的语义有些棘手,并且只能可靠地用于从对象中删除属性。将其他任何内容传递给它,你可能会或可能不会获得预期的结果。
不兼容的代码示例:
var x = 1;
delete x; // Noncompliant
function foo(){
..
}
delete foo; // Noncompliant
兼容解决方案:
var obj = {
x:1,
foo: function(){
...
}
};
delete obj.x;
delete obj.foo;
“delete”不应在数组上使用
delete可用于从任何对象中删除一个属性。数组是对象,因此delete也可以在此处使用运算符,但如果是,数组中将留下一个洞,因为索引/键不会移动以反映删除。
删除某个索引处的元素的正确方法是:
- Array.prototype.splice -从数组中添加/删除元素
- Array.prototype.pop -从数组末尾添加/删除元素
- Array.prototype.shift -从数组的开头添加/删除元素
不兼容的代码示例:
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
兼容解决方案:
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'
“ for ... in”循环应先对属性进行过滤,然后再对其进行操作
for...in语句使你可以遍历对象的所有属性的名称。属性列表包括通过原型链继承的所有那些属性。当对数据属性感兴趣时,这具有提供功能的副作用。不考虑这一点的程序可能会失败。
因此,每个for...in语句的主体都应该包含在一个if过滤器中,该过滤器将作用于哪些属性。它可以选择特定类型或值范围,也可以排除函数,也可以排除原型中的属性。
不兼容的代码示例:
for (name in object) {
doSomething(name); // Noncompliant
}
兼容解决方案:
for (name in object) {
if (object.hasOwnProperty(name)) {
doSomething(name);
}
}
“ indexOf”检查不应为正数
大多数针对indexO
f字符串或数组的调用检查都会将其与-1比较,因为0是有效索引。任何寻找值> 0的检查都会忽略第一个元素,这很可能是一个错误。如果仅检查字符串的存在,请考虑includes
改为使用 。在使用includes
方法之前 ,请确保你的浏览器版本支持该方法。
不兼容的代码示例:
var color = "blue";
var name = "ishmael";
var number = 123;
var arr = [color, name];
if (arr.indexOf("blue") > 0) { // Noncompliant
// ...
}
if (name.indexOf("ish") > 0) { // Noncompliant
// ...
}
兼容解决方案:
var color = "blue";
var name = "ishmael";
var number = 123;
var arr = [color, name];
if (arr.indexOf("blue") >= 0) {
// ...
}
if (name.includes("ish")) {
// ...
}
比较中不应使用“ NaN”
NaN不等于任何东西,甚至不等于任何东西。针对进行相等性或不相等性测试NaN将产生可预测的结果,但可能不是您想要的结果。
相反,查看变量是否等于的最佳方法NaN是使用Number.isNaN()ES2015
以来的,或者使用(也许是违反直觉的)将其与自身进行比较。从那时起NaN ! == NaN
,a ! == a
你知道它必须相等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
}
兼容解决方案:
if (Number.isNaN(a)) {
console.log("a is not a number");
}
if (!Number.isNaN(a)) {
console.log("a is not NaN");
}
“strict”模式应谨慎使用
即使强制执行JavaScript严格模式可能是一个好习惯,但这样做可能会导致尚不支持JavaScript严格模式的浏览器出现意外行为。因此,应谨慎使用此功能,并充分了解不支持此功能的浏览器的潜在后果。
不兼容的代码示例:
function strict() {
'use strict';
应该适当调用“ super()”
在某些情况下super()必须调用,而在某些情况下super()则不能调用。
基本规则是:非派生类中的构造函数无法调用super();派生类中的构造函数必须调用 super()。
此外:
-
super()必须先调用,然后才能使用
this
andsuper
关键字。 -
super()必须使用与基类的构造函数相同数量的参数来调用。
-
super()只能在构造函数中调用-不能在任何其他方法中调用。
-
super()不能在同一构造函数中多次调用。
不兼容的代码示例:
class Dog extends Animal {
constructor(name) {
super();
this.name = name;
super(); // Noncompliant
super.doSomething();
}
}
兼容解决方案:
class Dog extends Animal {
constructor(name) {
super();
this.name = name;
super.doSomething();
}
}
“ switch”语句不应嵌套
嵌套switch结构很难理解,因为你很容易将内部的情况混淆switch为属于外部的语句。因此,switch应避免使用嵌套语句。
具体来说,你应该对代码进行结构化,以避免需要嵌套switch语句,但是如果不能,则请考虑将内部结构switch移至另一个函数。
不兼容的代码示例:
function foo(n, m) {
switch (n) {
case 0:
switch (m) { // Noncompliant; nested switch
// ...
}
case 1:
// ...
default:
// ...
}
}
兼容解决方案:
function foo(n, m) {
switch (n) {
case 0:
bar(m);
case 1:
// ...
default:
// ...
}
}
function bar(m) {
switch(m) {
// ...
}
}