无论在什么开发岗位中,代码都通过开发者书写出来,后续也将由开发者去进行维护! 所以我们不难得出一个结论,如果要考虑代码优化的问题,无疑要从开发者视角去看! 这里引入 《计算机程序的构造和解释》 中提到的概念:
代码是写给人看的,不是写给机器看的,只是顺便计算机可以执行而已。如果代码是写给机器看的,那完全可以使用汇编语言或者机器语言(二进制),直接让机器执行。
作者强调的是,代码是写给人看的,所以要做到良好的编程风格,方便其他程序员阅读,维护。
基于以上来看,在我们开发过程中,要考虑对JavaScript
代码进行优化的话,可以从自己本身去入手这件事。或者说,从开发者角度去理解,比如说:
代码即计算机语言,比如说HTML
是超文本标记语言
。
和语言文字一样是为了表达思想、记载信息。所以写得清晰明了,能更有效地表达所要传递的信息。
前提: 如果当你需要花费一定
时间去浏览一段代码,才能弄清楚它到底要干什么的时候,那么这时候就应该尝试分解提炼这段代码了~
作用: 方便以后再读这段代码时,一眼就能清晰的知道这个函数的用途。
案例: 以一个公共导出方法为例
// 提炼前
exportExcel() {
let path = "/knowledge/excelExport";
let data = {
department: this.form.section,
departmentId: this.form.sectionId,
knowledgeType: this.documentType,
keyword: this.form.keyValue,
size: this.pageInfoConfig.rows,
current: this.pageInfoConfig.page,
mark: "export",
showAll: this.showAll ? "1" : "",
operateType: this.form.operateType,
};
this.exportExcelLoading = true;
axios({
method: "POST",
url: API_PATH + path,
data,
headers: {
'Content-Type': 'application/json;charset=UTF-8'
},
responseType: 'blob'
}).then(res => {
const content = res.data
const blob = new Blob([content])
const fileName = `${title}.xls`;
if ('download' in document.createElement('a')) { // 非IE下载
const elink = document.createElement('a')
elink.download = fileName
elink.style.display = 'none'
elink.href = URL.createObjectURL(blob)
document.body.appendChild(elink)
elink.click()
URL.revokeObjectURL(elink.href) // 释放URL 对象
document.body.removeChild(elink)
} else { // IE10+下载
navigator.msSaveBlob(blob, fileName)
}
this.exportExcelLoading = false;
}).catch(()=>{
this.$message.error('导出失败,请重试!');
});
},
// 提炼后
exportExcel() {
let path = "/knowledge/excelExport";
let data = {
department: this.form.section,
departmentId: this.form.sectionId,
knowledgeType: this.documentType,
keyword: this.form.keyValue,
size: this.pageInfoConfig.rows,
current: this.pageInfoConfig.page,
mark: "export",
showAll: this.showAll ? "1" : "",
operateType: this.form.operateType,
};
this.exportExcelLoading = true;
// 对应已经封装在文件中的导出方法
exportExcel(path, data, "导出信息-知识库").finally(() => {
this.exportExcelLoading = false;
});
},
> 文件中的导出方法
// 封装导出列表方法
import {API_PATH} from "@/config";
import axios from "axios";
import ElementUI from 'element-ui'
const exportExcel = (path, data, title) => {
return axios({
method: "POST",
url: API_PATH + path,
data,
headers: {
'Content-Type': 'application/json;charset=UTF-8'
},
responseType: 'blob'
}).then(res => {
const content = res.data
const blob = new Blob([content])
const fileName = `${title}.xls`;
if ('download' in document.createElement('a')) { // 非IE下载
const elink = document.createElement('a')
elink.download = fileName
elink.style.display = 'none'
elink.href = URL.createObjectURL(blob)
document.body.appendChild(elink)
elink.click()
URL.revokeObjectURL(elink.href) // 释放URL 对象
document.body.removeChild(elink)
} else { // IE10+下载
navigator.msSaveBlob(blob, fileName)
}
}).catch(()=>{
ElementUI.Message.error('导出失败,请重试!');
});
};
export default exportExcel;
以上提炼函数的方法,不仅可以提高代码复用率,还可以使暴露出来的代码更加简洁明了,方便统一维护导出方法!
Tips: 不过需要注意的是,在提炼函数时,需要明确目的性。不能以提炼而提炼,过分的封装提炼,只会显得代码庸余且
绕
!
前提: 具有相似操作逻辑的函数,增加参数用以区分不同操作。
作用: 增加函数接收参数的个数,减少编写相似函数的编写。
案例: 以上面封装的导出方法为例,传入不同的path、data、title
等等。用于区分导出的文件名称和请求的接口!
exportExcel(path, data, "导出信息-知识库");
前提: 当分支语句过于臃肿时,可以使用策略模式来取代分支语句
作用: 当if-else或者switch-case分支过多时可以使用策略模式将各个分支独立出来。减少代码量,使代码更加简洁高效。
案例:
// ==================重构前==================
function getPrice(tag, originPrice) {
// 新人价格
if(tag === 'newUser') {
return originPrice > 50.1 ? originPrice - 50 : originPrice
}
// 返场价格
if(tag === 'back') {
return originPrice > 200 ? originPrice - 50 : originPrice
}
// 活动价格
if(tag === 'activity') {
return originPrice > 300 ? originPrice - 100 : originPrice
}
}
// ==================重构后==================
const priceHandler = {
newUser(originPrice){
return originPrice > 50.1 ? originPrice - 50 : originPrice
},
back(originPrice){
return originPrice > 200 ? originPrice - 50 : originPrice
},
activity(originPrice){
return originPrice > 300 ? originPrice - 100 : originPrice
}
}
// 实际使用的方法,传入所要使用的方法名
function getPrice(tag, originPrice){
return priceHandler[tag](originPrice)
}
逻辑运算符
/ 三元运算符
替代分支语句前提: 当分支语句不多时,可以使用运算符代替。实现分支语句的功能。
作用: 减少代码量,使代码更加简洁高效。
案例:
// 案例一
// ==================== 重构前 ====================
function getInfoByID(id, place) {
if(id && place) {
...
} else {
this.$message('无法通过编号 + 地点获取信息')
}
}
// ==================== 重构后 ====================
function getInfoByID(id, place) {
const fn = ((id && place) ?() => {
// 执行内容
} : () => {
this.$message('无法通过编号 + 地点获取信息')
})
fn()
}
// 案例二: 单一分支语句
// ==================== 重构前 ====================
if(id && place) {
...
}
if(!(id && place)) {
...
}
// ==================== 重构后 ====================
(id && place) && (() => { 执行内容 })()
!(id && place) || (() => { 执行内容 })()
卫语句简述: 如果某个条件极其罕见,就应该单独检查该条件,并在该条件为真时立刻从函数中返回。 这样的单独检查常常被称为“卫语句”(guard clauses)。
应用场景: 当分支语句放在需要输出结果的函数内时, 当某个条件成立,无需关心其余内容的情况。即可使用 ”卫语句
“
if-else结构: 代表对
if分支
和else分支
的重视是同等的。这样的代码结构传递给阅读者的消息就是:各个分支有同样的重要性。
卫语句:卫语句则是告诉阅读者: “这种情况不是本函数的核心逻辑所关心的, 如果它真发生了,请做一些必要的整理工作,然后退出。” 为了传递这种信息可以使用卫语句替换嵌套结构。
// ==================重构前==================
function payAmount(employee) {
let result;
if(employee.isSeparated) {
result = {amount: 0, reasonCode:"SEP"};
}
else {
if (employee.isRetired) {
result = {amount: 0, reasonCode: "RET"};
}
else {
result = someFinalComputation();
}
}
return result;
}
// ==================重构后==================
function payAmount(employee) {
if (employee.isSeparated) return {amount: 0, reasonCode: "SEP"};
if (employee.isRetired) return {amount: 0, reasonCode: "RET"};
return someFinalComputation();
}
🔥 < 今日份知识点: 浅述对函数式编程的理解 及其 优缺点 >
🔥 < 每日知识点:关于Javascript 精进小妙招 ( Js技巧 ) >