先抛出两个问题,检查下是否是前端新手,本文所讲是纯原生JavaScript语法,不涉及任何框架。
问题1,阅读如下代码,当a等于undefined、null、false、true、"abc"时,b和c的值是多少?
const b = a ?? "hello";
const c = a || "hello";
问题2,阅读如下代码,最终输出a的值是多少?
a = 1;
a = ++a;
console.info(a);
以上两个问题如果非常了解的话,大概率说明已经入门了。
if、else的优化
如果实例不为空则执行方法,如下写法
//不简洁的写法
if (obj) {
obj.test();
}
//简化1
obj && obj.test && obj.test();
//还可以进一步简化
obj?.test();
同样的,访问一个复杂对象的一个成员变量,如下写法:
//不优雅的写法
let a;
if (obj && obj.child1 && obj.child1.a) {
a = obj.child1.a;
}
//同样的,使用?号操作符进行简化,一行代码搞定
let a = obj?.child1?.a;
根据条件判断赋值
// 不简洁的写法
let a;
if(value) {
a = value;
} else {
a = defaultValue;
}
// 简化1,基本的语法,几乎所有编程语言都会
a = value ? value : defaultValue;
// 简化2,对应开头的问题1,??和||什么区别呢?
a = value || defaultValue;
解答下问题1的疑问,??和||运算符的区别,||是将前面的值转换成boolean后,如果是true则取其前面的值,否则取后面的值。而双问号则为:前面的值为null、undefined,则取后面的值,否则都取前面的值。也就是说,如果value等false的时候想让a等false,那么就用??运算符。
回调函数转Promise风格
先看如下代码:
//有些人可能会这样写js方法,如下test2要在test1回调成功后执行
function test1 (arg1, callback1, errorCallback) {}
function test2 (arg1, callback1, errorCallback) {}
//然后使用的时候,就可能会演变成这样
test1("abc", (resp1) => {
//回调成功后执行test2
test2("cde", resp2 => {
console.info('test2执行完成', resp2);
}, error => console.log(error));
}, (errorMsg) => {
console.error(errorMsg);
});
上面的代码看起来很垃圾,非常不简洁,不易读,上面只是列举了两层,如果还有test3、test4岂不是很恐怖,这便是回调地狱。
那么如何解决回调地狱呢?
首先,不传入callback,而是返回Promise,本文不对Promise做过多的解释,只抛出名词,可自行查阅资料;
然后在then中处理结果和执行下一个方法,最后catch异常,finally中做最后的收尾工作。
对象赋值操作
不多说了,直接写代码实例了
let obj1 = {a: 2, b: 4}
//轻量级clone,注意这种方式不会拷贝原型,啥是原型(prototype)?答:自行查阅资料
let obj2 = {...obj1};
//clone并增加新属性,或覆盖旧属性
let obj3 = {...obj1, a: 6, c: "hello"};
上述代码,...运算符对数组同样适用。
重量级的clone要考虑其原型和其子成员的原型,通常会引用第三方的库,自己实现比较复杂。
数组操作,简化for循环
let array = [4,2,6,9,1,3,7]
//过滤 + 排序,如下代码会过滤掉1和2,并对剩下的进行排序
const result = array.filter(a => a > 2).sort((a, b) => a - b);
//使用map映射成另一种类型的数据,如下转换为A类的实例数组
const aList = array.map(a => new A(a));
//流式操作,最后遍历处理
array.filter(a => a > 2).map(a => new A(a)).forEach(a => {
//处理A的实例
});
好了,先说这么多吧,我也只是个业余前端,主要搞后端Java的。我的开源作品中也有涉及前端,欢迎访问:GitHub推荐Java进程启动器—Jarboot 其中jarboot-ui模块是前端部分,使用了React技术。