< 每日技巧: JavaScript代码优化 >

代码优化


👉 前言

无论在什么开发岗位中,代码都通过开发者书写出来,后续也将由开发者去进行维护! 所以我们不难得出一个结论,如果要考虑代码优化的问题,无疑要从开发者视角去看! 这里引入 《计算机程序的构造和解释》 中提到的概念:

代码是写给人看的,不是写给机器看的,只是顺便计算机可以执行而已。如果代码是写给机器看的,那完全可以使用汇编语言或者机器语言(二进制),直接让机器执行。

作者强调的是,代码是写给人看的,所以要做到良好的编程风格,方便其他程序员阅读,维护。

俯瞰

基于以上来看,在我们开发过程中,要考虑对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技巧 ) >

🔥 < 今日份知识点:谈谈内存泄漏 及 在 Javascript 中 针对内存泄漏的垃圾回收机制 >

🔥 < 今日份知识点:浅述对 “ Vue 插槽 (slot) ” 的理解 以及 插槽的应用场景 >

评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

技术宅小温

你小小的鼓励,是我搬砖的动力!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值