使用闭包函数优化思维,重构代码

前言

闭包多是用匿名函数实现,在匿名函数中引用了外部变量,那这个匿名函数就形成了闭包。匿名函数拥有可动态编程的执行过程。巧妙使用可以让你的代码简约而不失优雅,灵活而不失约束。好了,正式切入本文的正题,使用闭包函数优化思维,重构代码。

下面是三种场景中对闭包的使用

使用闭包遍历水果选择项

闭包的声明语法:(function(参数){}(值))
在声明的时候传值,该闭包函数会立即执行,例如下面代码中的fruitsItems函数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<div id="fruits-items"></div>
<script type="text/javascript">
// 遍历石榴,李子,橘子,生成水果复选框代码
// 测试“声明的时候传值,该闭包函数会立即执行”
let fruitsItems = (function(fruits) {
return fruits.map(it => '<label><input type="checkbox" name="' + it.name + '" title="' + it.title + '"/>' + it.title + '</label>').join('<br>');
}([
{name: 'pomegranate', title: 'Pomegranate'},
{name: 'plum', title: 'Plum'},
{name: 'tangerine', title: 'Tangerine'}
]));
// 闭包中使用匿名函数
let fruits = (function() {
return {
setItems: function(array_items) {
return array_items.map(it => '<label><input type="checkbox" name="' + it.name + '" title="' + it.title + '"/>' + it.title + '</label>').join('<br>');
}
}
}())
// 赋值
$('#fruits-items').html(fruits.setItems([
{name: 'apple', title: 'Apple'},
{name: 'banana', title: 'Banana'}
])).append('<br>').append(fruitsItems);
</script>

筛选出年级小于并等于25岁的女性同事

筛选前

姓名:Winnie,年龄:25,性别:female
姓名:Jim,年龄:29,性别:male
姓名:Anson,年龄:27,性别:male
姓名:Danica,年龄:23,性别:female

筛选后

姓名:Winnie,年龄:25,性别:female
姓名:Danica,年龄:23,性别:female

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
<div>筛选前</div>
<div id="workmates"></div>
<div>筛选后</div>
<div id="filtered-workmates"></div>
<script type="text/javascript">
let wms = (function() {
var datas = [
{name: 'Winnie', age: 25, sex: 'female'},
{name: 'Jim', age: 29, sex: 'male'},
{name: 'Anson', age: 27, sex: 'male'},
{name: 'Danica', age: 23, sex: 'female'}
];
return {
init: function() {
return this.htmls(datas);
},
filter: function(fn) {
let filtered = [];
for (let i = 0; i < datas.length; i++) {
// 重点:将遍历对象传递出去,任意开发人员进行条件设置,满足了就被筛选成功
if (fn(datas[i], i) === true) {
filtered.push(datas[i]);
}
}
return this.htmls(filtered);
},
htmls: function (renders) {
return renders.map(wm => '<label>姓名:' + wm.name + ',年龄:' + wm.age + ',性别:' + wm.sex +'</label>').join('<br>');
}
}
}());
$('#workmates').html(wms.init());
$('#filtered-workmates').html(wms.filter(wm => wm.age <= 25 && wm.sex === 'female'));
</script>

实现一个数据处理过程的匿名函数重构

传入 5
执行成功返回 {status: ‘success’, data: 10}
执行失败返回 {status: ‘failed’, error: ‘xxx’}
传入 [2, 3]
执行成功返回 {status: ‘success’, data: [{status: ‘success’, data: 4}, {status: ‘success’, data: 6}]}
执行失败返回 {status: ‘success’, data: [{status: ‘failed’, error: ‘xxx’}, {status: ‘failed’, error: ‘xxx’}]}

普通js代码

代码冗余,相同的代码重复写,机械化。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
function multiple(inNum) {
if (Array.isArray(inNum)) {
return {
status: 'success',
data: inNum.map(it => {
if (isNaN(parseFloat(it))) {
return {
status: 'failed',
error: 'the input is not a number'
}
}
return {
status: 'success',
data: it * 2
};
});
}
} else {
if (isNaN(parseFloat(inNum))) {
return {
status: 'failed',
error: 'the input is not a number'
}
}
return {
status: 'success',
data: inNum * 2
};
}
}

重构后

execute 方法只管输入输出的格式和错误处理,包揽了所有脏活累活;multiple 方法则只关心业务的具体实现,也不用关心输入的是单个元素还是数组。如果要改乘 3,只要修改 multiple 方法最后一个 return。优秀!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
function execute(data, fn) {
let single = it => {
try {
return {
status: 'success',
data: fn(it)
}
} catch (e) {
return {
status: 'failed',
data: e.toString()
}
}
};
if (Array.isArray(data)) {
return {
status: 'success',
data: data.map(single)
};
} else {
return single(data);
}
}
function multiple(inNum) {
return execute(inNum, it => {
if (isNaN(parseFloat(it))) {
throw new Error('the input is not a number');
}
return it * 2;
})
}

结尾

本文练习总结结果源于阅读“微信公众号:前端早读课”的“【第1073期】巧用匿名函数重构你的代码”一文,进行自身场景的练习,转换成技能为我所用。
本文只做日常技术知识积累记录所用,侵删。