文章目录
1. 使用"逻辑或"设置初始值
此方法不识别数值 0:【0 被转为布尔值 false,跳过执行】
function fn(val) {
return val = val || '默认值';
}
fn(0); // '默认值'
fn(); // '默认值'
应改为 “if” 语句:
function fn(val) {
if (val !== 0) val = val || '默认值';
return val; // 注意,判断不含 0,所以返回值要单独写
}
fn(0); // 0
fn(); // '默认值'
或改为三元表达式:
function fn(val) {
return val = (val === 0 ? 0 : (val ? val : '默认值'));
}
fn(0); // 0
fn(); // '默认值'
2. 初始值为 undefined 与 null 的区别
在运算时,"undefined"会被转为数值 NaN,“null” 则被转为数值 0。
另外,0 是数值中的空值。
undefined == null; // true
undefined === null; // false
isNaN(undefined); // true
isNaN(null); // false
var a = a || undefined;
a + 1; // NaN
var b = b || null; // 等同于 var b = b || 0;
b + 1; // 1
3. 计算时避免运算子进行字符串拼接
有时候需要一个参数既可以为字符串,又可以为数值。
但在 JavaScript 中,只要其中一个运算子为字符串,相加时都将会进行拼接运算:
function fn(val) {
return val + 1;
}
fn('1'); // '11'
转换方法有很多,最常用的是【减乘除指数算术运算符】、【Number()】:
function fn(val) {
return val/1 + 1;
// (val - 0)
// val * 1
// val ** 1
// Number(val) + 1;
}
fn('1'); // 2
4. 为了易读与排错,应谨慎(尽量不使用)“短路”
"短路"规则不适用于多条执行,否则易出错:【没有判断控制,会优先执行最上面一条】
function fn(a, b) {
return isNaN(a) || isNaN(b) ? '不是数字' : '是数字'; // 优先执行
return a > 10 || b < 0 ? '非法值' : '合法值'; // 永远不执行
}
fn('a', 'b'); // '不是数字'
fn(11, -1); // '是数字'
应改为 “if” 语句:
function fn(a, b) {
if (isNaN(a) || isNaN(b)) return '不是数字';
if (a > 10 || b < 0) return '非法值';
}
fn('a', 'b'); // '不是数字'
fn(11, -1); // '非法值'
5. 函数体内覆盖变量值
- 错误写法:
var num = 123;
function fn(n) {
n = 999;
}
fn(num);
num; // 123
这是由于形参相当于在函数内部隐式声明的局部变量,所以无法覆盖外部变量。
- 相当于:
var num = 123;
function fn() {
var num = 999;
}
fn();
num; // 123
- 正确写法:
// 内部直接覆盖
var num = 123;
function fn() {
num = 999;
}
fn();
num; // 999
/* ----------------------------------------------- */
// 函数返回一个结果,赋值给原变量
var num = 123;
function fn() {
n = 999;
return n;
}
num = fn();
num; // 999;
6. 关于数据转换为字符串
- 错误用法
// 数组、对象:无法直接转为字符串
([]).toString(); // '' 【某些时候则有用】
({}).toString(); // '[object Object]'
// 正则、函数、undefined:无法通过 stringify() 正确获取字符串
JSON.stringify(new RegExp); // '{}'
JSON.stringify(function() {}); // undefined
JSON.stringify(undefined); // undefined
// 数组存在 null、undefined 元素时:
[null, undefined].toString(); // ','
JSON.stringify([null, undefined]); // '[null,null]'
- 正确用法【逐个对应】:
// 数组、对象:使用 stringify() 方法
JSON.stringify([]); // '[]'
JSON.stringify({}); // '{}'
// 正则、函数、undefined:直接转换
(new RegExp).toString(); // '/(?:)/'
(function() {}).toString(); // 'function() {}'
undefined+''; // 'undefined'
// 数组存在 null、undefined 元素时,遍历拆分,分别转为字符串再重组
var _arr = [null, undefined];
var getStr = function(arr) {
var item = '';
for (var i = 0, len = arr.length; i < len; i++) {
if (i < len-1) {
item += arr[i] + ',';
} else {
item += arr[i] + '';
}
}
return '[' + item + ']';
}
getStr(_arr); // '[undefined,null]'
7. typeof 无法正确判断的数据类型
// 对象、数组、日期、正则均判断为对象(它们都是对象类型)
typeof {}; // 'object'
typeof []; // 'object'
typeof /^$/; // 'object'
typeof (new Date); // 'object'
// null 是特殊的对象
typeof null; // 'object'
8. instanceof 无法正确判断的数据类型
// 由于instanceof检查整个原型链,因此同一个实例对象,可能会对多个构造函数都返回true
([]) instanceof Array; // true
([]) instanceof Object; // true
(new Date) instanceof Date; // true
(new Date) instanceof Object; // true
// 不能用来判断原始值
'str' instanceof String; // false
- 可以通过
Object.prototype.toString.call();
来区分引用类型数据
Object.prototype.toString.call({}); // '[object Object]'
Object.prototype.toString.call([]); // '[objcet Array]'
Object.prototype.toString.call(function(){}); // '[object Function]'
Object.prototype.toString.call(new Date); // '[object Date]'
Object.prototype.toString.call(/^$/); // '[object RegExp]'
9. 递归需 return 才会有返回值
- 错误写法
// 倒数获取与 '<!>' 之间不超过 5 个元素的 '' 的位置
const arr = [
'',
'',
'asd',
'',
'asdasd',
'xxx',
'',
'<!>',
'',
'sdas'
];
const end = arr.indexOf('<!>');
const start = (function getIndex(i) {
let index = arr.lastIndexOf('', i);
if (end - index < 5) {
i--;
getIndex(i); // 没有 return
} else {
return index;
}
})(end);
console.log(start); // undefined
- 正确写法
// 倒数获取与 '<!>' 之间不超过 5 个元素的 '' 的位置
const arr = [
'',
'',
'asd',
'',
'asdasd',
'xxx',
'',
'<!>',
'',
'sdas'
];
const end = arr.indexOf('<!>');
const start = (function getIndex(i) {
let index = arr.lastIndexOf('', i);
if (end - index < 5) {
i--;
return getIndex(i); // 此处也需要 return
} else {
return index;
}
})(end);
console.log(start); // 1