目的
在不考虑兼容以及工具的支持下,使用最新的API,以达到简洁与个人的知识更新。
ES6部分参考:
MDN官方文档
ECMAScript 6 入门
目录
- Obect 对象操作
- Array 数组操作
- String 字符串操作
- Number 数字操作
- 其他功能整合
1,Obect 对象操作
在对象内,声明一个变量为属性名
//bad
var keys = 'listName';
var obj = {};
obj[''+keys ] = xxx;
//good
var keys = 'listName';
var obj = {
[keys]: xxx;
};
//在对象用内 []声明属性key,可以[]进行简单数据操作(复杂也可以,不推荐);
var aa = 'hello';
var bb = 'world';
var obj1 = {
[aa+bb]: 123;
[bb+aa]() { // 等同于 worldhello:function (){}
console.log(321);
}
}
console.log(obj1.helloworld); // 123;
obj1.worldhello(); //321;
Object.assign 浅复制
//Object.assign(target, source1, source2);
//bad
var default_opt = {
name: 'default',
times: 10000
}
var params_opt = {
name: 'name1'
}
for( var key in default_opt ) {
if( typeof params_opt[key] === 'undefind' ){ //如果直接用 if( params_opt[key] ) 会漏过 false 0 '' 等值
params_opt[key] = default_opt[key]
}
}
//good
Object.assign(default_opt ,params_opt ); //更多用法参考文档
//注意点,Object.assign()是浅拷贝,对于被拷贝的对象中存在嵌套对面的情况,
//这个时候的拷贝只是引用的同一个对象,在修改复制后的对象中的嵌套对象时,
//会引起被拷贝的对象中的嵌套对象改变,
//个人的建议是,利用Object.assign() 这一特性,自己编写一个深度拷贝。
对象属性key遍历 Object.keys
var obj = { aaa :123, bbb :323};
//bad
for(var key in obj) {
console.log(obj[key])
}
//good
Object.keys(obj).forEach( item => {
console.log(obj[item]);
})
//更多类似的Object取属性key value用法
//Object.values(obj) => [123,323]
//Object.values(obj) => [['aaa':123],['bbb',323]]
2,Array 数组操作
主要涉及到以下method
- Array.from()
- Array.forEach()
- Array.reduce()
- Array.map()
- Array.filter()
- Array.some()
- Array.every()
类数组转数组 Array.from()
一般用作获取arguments、NodeList等一类的类数组转化为数组,从而进行操作。
//老旧用法 for循环的用法更low 就不展示了
function getInputValue() {
var tmp_arr = [];
[].forEach.call(document.querySelectorAll('input[name="like"]'),function (item) {
tmp_arr.push(tmp_arr.value);
})
return tmp_arr.join(',');
}
//替换用法
function getInputValue() {
var tmp_arr = [];
Array.from(document.querySelectorAll('input[name="like"]'),forEach(function (item) {
tmp_arr.push(tmp_arr.value);
})
return tmp_arr.join(',');
}
//更高级的用法 reduce 可以不使用 tmp_arr 临时变量
数组循环 Array.forEach()
我觉得这个没有必要上代码,只要尽量避免在js 用 for 循环去循环一个数组
数组累加器 Array.reduce()
在 针对数组中的要进行字符串拼接,有着得天独厚的优势
//一般的用法
var arr = [
{ name: '小赵'},
{ name: '小钱'},
{ name: '小孙'},
{ name: '小李'}
];
//一般的用法
function getNames() {
var tmp_str = '';
arr.forEach( item => {
tmp_str += item.name + ' ';
});
return tmp_str;
}
//更好用法
function getNames() {
return arr.reduce((total,item) => {
return `${total} ${item.name}`
},'');
}
然而 `` 跟 ${} 又是什么 ,那就等看一下 String 的扩展了
基于一个数组生成新数组 Array.map()
基于一个数组,可以循环该数组的每个成员并返回拿到成员值做特殊处理的结果,重新组成新数组
var arr = [9,8,10,11,12];
//bad
var new_arr = [];
arr.forEach( item => {
new_arr.push( item * 10 );
})
//good
var new_arr;
new_arr = arr.map( item => {
return item * 10
})
//这个也没什么必要讲
数组过滤器 Array.filter()
过滤一个数组,对一个数据进行数据筛选,并返回一个通过的筛选值组成的新数组
var arr = [9,8,10,11,12];
//bad
var new_arr = [];
arr.forEach( item => {
if( item >= 10){
new_arr.push( item * 10 );
}
})
//good
var new_arr;
new_arr = arr.filter( item => {
return item >= 10;
})
数组循环判断 Array.some()
这个用得比较多,作用就是去 替换 数组for循环中存在终止条件break
var arr = [
{id:1,isSelected:false},
{id:2,isSelected:true},
{id:3,isSelected:false}
];
var flag_has_select = false;
//bad A
var i;
var len;
for( i = 0,len = arr.length; i < len; i++) {
if( arr[i].isSelected ) {
flag_has_select = true;
break;
}
}
//bad B
arr.forEach( item => {
if( item.isSelected ){
flag_has_select = true;
//forEach 无法中断
}
})
//good
flag_has_select = arr.some( item => {
return item.isSelected;
//if( item.isSelected ) { return true}
})
数组循环判断 Array.every()
var arr = [
{id:1,isSelected:false},
{id:2,isSelected:true},
{id:3,isSelected:false}
];
var flag_all_select = true;
//bad
arr.forEach( item => {
if( !item.isSelected ){
flag_all_select = false;
}
})
//good
flag_all_select = arr.every( item => {
return item.isSelected;
})
3,String 字符串操作
最明确的一点 不再出现 html += 'xxx' + xxx + 'xxx' 这类的操作,该用模板引擎的用模板引擎,该 字符串 拼接的 采用 `反引号 与 ${ 变量 }拼接。
模板字面量
//bad A
html = '/api/user/' + useId;
//good A
html = `api/user/${userId}`;
//bad B
data.forEach( item => {
html += '<li>' + item.name + '</li>';
})
//good B
data.forEach( item => {
//在能够确认数据不会包含 xss 攻击 且 dom 字符拼接较少时
html += `<li>${item.name}</li>`;
//当数据存在包含 xss 攻击的可能性 或者 大量的 dom 字符拼接
html += template(item);
//xss 攻击中的一种主要是用户通过输入信息包含 <script> 脚本语言 对用户信息的盗用
//最简单的就是 将用户的输入的数据 用正则将 ‘<’ ‘>’ 转化成 > <
})
4,Number 数值操作
最明确的一点 一切数值、字符串判断 用 === 强等进行
虽然JavaScript是弱类型语言,但是对自己的代码要以强类型的去对待。虽然有些判断 == 也没有问题,但是要养成良好的数据类型预定与判断(flow js数据类型检验工具)
Number()
var input_val = document.getElementById('input').value;
//bad A
if( input_val == 2 ) {}
//good A
if( Number(input_val ) === 2) {}
var show_text_span = document.getElementById('count_span');
//bad B
show_text_span.innerText = 1 + input_val ;
//good B
// 避免 1 + ‘0’ = ‘10’ 的情况出现;
// 当然一般不是这么写, input_val还要用过 isNaN之类的判断,这里假设input_val是 数值型的字符串
show_text_span.innerText = 1 + Number(input_val) ;
5,其他功能整合
1. 不要过度的使用 if else / if esle if else 嵌套
太多的if else嵌套给阅读代码的人容易造成一种难以快速理解的感觉
//bad
function getSelectInfo(obj){
var text = ''
if( obj.isSelected ) {
text = '已选中';
} esle {
text = ‘未选中’;
}
return text;
}
//better
function getSelectInfo(obj){
var text = '未选中'
if( obj.isSelected ) {
text = '已选中';
}
return text;
}
有时候,换一个策略,可能使得代码更简洁。
var data = { key: 'sending' || 'sended' || 'ok' || 'error'} //后面的可能会出现其中一个
//bad 这代码我看着难受
function getSendStatus(dataObj){
var text = ''
if( dataObj.key === 'sending' ) {
text = '发送中';
} esle if( dataObj.key === 'sended') {
text = ‘已发送’;
} else if( dataObj.key === 'ok' ) {
text = ‘发送成功’;
} else if( dataObj.key === 'error' ) {
text = ‘发送出错’;
}
return text;
}
// 小知识点,js 中 只有 if else 没有 if else if else? 真的吗?查查
//虽然可以采用 switch 做一下优化,但是条件多总给人一种需要花费时间去理解的感觉
//better
var status_obj = {
'sending': '发送中',
'sended': '已发送',
'ok': '发送成功',
'error': '发送出错'
};
// 如果status_obj 是一次性的 那么可以放在getSelectInfo内部,
// 如果多次使用 考虑与getSelectInfo 采用 单例模式 ,避免暴露更多的无用变量到上层作用域;
function getSelectInfo(dataObj){
return status_obj[dataObj.key];
}
// 当然 上面的代码是肯定已经肯定 data.key只有4个值,
// 在实际生产当中总是需要考虑一个默认值用于超出预期处理