案例:计算器的实现代码
普通人怎么写的:
html部分
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>es5程序设计</title>
</head>
<body>
<div>
结果: <h1>0</h1>
<input type="text" name="" id="" value="0">
<input type="text" name="" id="" value="0">
<div class="btn-group">
<button data-val="add">+</button>
<button data-val="jie">-</button>
<button data-val="cheng">*</button>
<button data-val="chu">/</button>
</div>
</div>
</body>
<script src="./tools.js"></script>
<script src="./2.js"></script>
</html>
结果:
0
+ - * /
js部分
var result = document.getElementsByTagName('h1')[0],
inp = document.getElementsByTagName('input'),
div = document.getElementsByClassName('btn-group')[0]
div.addEventListener('click', onBtnClick, false);
function onBtnClick (ev) {
var e = ev || window.EventTarget,
tar = e.target || e.srcElement,
tagName = tar.tagName.toLowerCase()
if (tagName === 'button') {
var method = tar.getAttribute('data-val'),
fVal = Number(inp[0].value.replace(/\s+/g, '')) || 0,
lVal = Number(inp[1].value.replace(/\s+/g, '')) || 0
switch (method) {
case 'add':
result.innerText = fVal + lVal
break;
case 'jie':
result.innerText = fVal - lVal
break;
case 'cheng':
result.innerText = fVal * lVal
break;
case 'chu':
result.innerText = fVal / lVal
break;
default:
break;
}
}
}
在我看来,代码写的没有什么啊,又用了事件代理,做了ie兼容,也用switch来代替else。
别人眼里,全局变量和全局方法太多,容易操作变量名污染。
解决方案
再生成一个独立作用域,直接把代码写成一个自执行函数。
// 使用一个独立作用域,也就是立即执行函数
; (function () {
var result = document.getElementsByTagName('h1')[0],
inp = document.getElementsByTagName('input'),
div = document.getElementsByClassName('btn-group')[0]
div.addEventListener('click', onBtnClick, false);
function onBtnClick (ev) {
var e = ev || window.EventTarget,
tar = e.target || e.srcElement,
tagName = tar.tagName.toLowerCase()
if (tagName === 'button') {
var method = tar.getAttribute('data-val'),
fVal = Number(inp[0].value.replace(/\s+/g, '')) || 0,
lVal = Number(inp[1].value.replace(/\s+/g, '')) || 0
switch (method) {
case 'add':
result.innerText = fVal + lVal
break;
case 'jie':
result.innerText = fVal - lVal
break;
case 'cheng':
result.innerText = fVal * lVal
break;
case 'chu':
result.innerText = fVal / lVal
break;
default:
break;
}
}
}
})()
我的眼里完美解决。
别人眼里:你这个写的不怎么规范!
进一步修改
; (function () {
var oResult = document .getElementsByTagName('h1')[0],
inp = document .getElementsByTagName('input'),
btnGroup = document .getElementsByClassName('btn-group')[0]
// 初始化函数 管理这个模块的运行
var init = function () {
bindEvent()
}
function bindEvent () {
btnGroup.addEventListener('click', onBtnClick, false);
}
function onBtnClick (ev) {
var e = ev || window.EventTarget,
tar = e.target || e.srcElement,
tagName = tar.tagName.toLowerCase()
if (tagName === 'button') {
var method = tar.getAttribute('data-val'),
fVal = Number(inp[0].value.replace(/\s+/g, '')) || 0,
lVal = Number(inp[1].value.replace(/\s+/g, '')) || 0
switch (method) {
case 'add':
result.innerText = fVal + lVal
break;
case 'jie':
result.innerText = fVal - lVal
break;
case 'cheng':
result.innerText = fVal * lVal
break;
case 'chu':
result.innerText = fVal / lVal
break;
default:
break;
}
}
}
}
init()
})()
这个时候:别人看不下去,直接告诉你问题。
- document 应该是window,每次使用都要去寻找,应该用实参传入的方法;
- 字符串变成数字是不是一个可以封装成为工具类的方法
- ie兼容性问题是不是可以也封装成为一个工具类。
- onBtnClick 是不是管理事情过多,数据判断是不是一个功能函数,应该另行封装?
- dom节点的渲染,是不是不应该写在功能函数里面呢?
最终方案
// 使用一个独立作用域,也就是立即执行函数
; (function (doc, tools) {
// document 属于window
var oResult = doc.getElementsByTagName('h1')[0],
inp = doc.getElementsByTagName('input'),
btnGroup = doc.getElementsByClassName('btn-group')[0]
// 初始化函数 管理这个模块的运行
var init = function () {
bindEvent()
}
function bindEvent () {
btnGroup.addEventListener('click', onBtnClick, false);
}
function onBtnClick (ev) {
// var e = ev || window.EventTarget,
// tar = e.target || e.srcElement,
var tar = tools.getTarget(ev)
tagName = tar.tagName.toLowerCase()
if (tagName === 'button') {
var method = tar.getAttribute('data-val'),
// 去除空格应该属于一个工具类,应该可以重复使用。
// fVal = Number(inp[0].value.replace(/\s+/g, '')) || 0,
// lVal = Number(inp[1].value.replace(/\s+/g, '')) || 0
fVal = tools.digtalize(inp[0].value),
lVal = tools.digtalize(inp[1].value)
// compute(method, fVal, lVal)
renderResult(compute(method, fVal, lVal))
}
}
function renderResult (res) {
oResult.innerText = res
}
// 功能函数
function compute (method, val1, val2) {
// 问题:不应该管理渲染结果
switch (method) {
case 'add':
return val1 + val2
case 'jie':
return val1 - val2
case 'cheng':
return val1 * val2
case 'chu':
return val1 / val2
default:
break;
}
}
init()
})(document, initTools)
tools.js文件
var initTools = (function () {
function digtalize (str) {
return Number(str.replace(/\s+/g, '')) || 0
}
function getTarget (ev) {
var e = ev || window.EventTarget
return e.target || e.srcElement
}
return {
digtalize: digtalize,
getTarget: getTarget
}
})();
html
结果:
0
+ - * /
听别人说,看别人的代码都能赏心悦目。可能说就是可以写的代码吧。
命名可能不太规范,看看就好,重要的还是大佬们的思想。
本文主要借鉴b站视频教程,主要还是记录给日后自己参考,对他人借鉴意义可能不大,建议可以直接过去看原视频。
借鉴视频地址:https://b23.tv/5Ic7BR