近来在看《javascript设想形式与开辟实践》。
var calc = function(level,salary){
if(level === "A"){
return 3*salary
}
if(level === "B"){
return 2*salary
}
if(level === "C"){
return 1*salary
}
}
这段代码看起来非常简朴,然则跟着后期的拓展,要增添更多的if语句,calc函数会变得越发巨大,不易于保护。
假如我要修正原有的盘算分之,能够每次都要修正calc这个要领。实际上,这个calc这个要领的设想初志只是为了返回 绩效工资。
在全部代码的别的部份,能够还须要这个盘算要领,岂非还要copy一份过去么,那末一样的修正要修正两块代码。
用战略形式来重构代码
战略形式指的是定义一系列的算法,把他们一个个都封装起来。将稳定的部份和变化的部份支解最先每一个设想形式的主题,战略形式的目标就是将算法的运用与算法的完成星散开来。
再说上边的需求,我们简朴思索下,实在变化的部份就是员工的品级和工资,而我们的目标就是返回绩效工资这部份是稳定的
// 依据员工的level和salary 金额的盘算
var straigies = {
“A”: function(salary){
return fn*3
},
“B”: function(salary){
return fn*2
},
“C”: function(salary){
return fn*1
}
}
//稳定的部份
var calc = function(level,salary){
return straigies[level](salary)
}
// 实行
calc("A",5000) // => 15000
比较下两段代码,不见了不友好的 if推断,算法(战略)都放在了straigies 中,后续需求 只须要保护straigies对象即可。
用战略形式来重构表单考证
许多须要提交表单的营业场景,都须要以下构造的代码
$('submitBtn').on('click',functioin(){
if($name.value().length < 6){
console.log("用户名长度不能少于6")
}
if($phone.value() != ''){
console.log("电话号码不能为空")
}
ajaxFn()
})
跟着 推断前提的增添,函数的构造会愈来愈痴肥巨大,而须要修正推断的前提,就又要深切指定的if推断去挑选,纯真的新增划定规矩在这个函数里,复用性太差。连系战略形式,能够把if推断这一部份 函数里提取出来从新封装,进步代码的复用性和可读性。
对代码构造的希冀
$('submitBtn').on('click',functioin(){
var form = document.querySelector('.form');
var validator = new validator ();
validator.addrules(form.username,"isNonEmpty","不能为空")
validator.addrules(form.phone,"minLength:6","起码为6位")
var erroMsg = validator.start();
if(erroMsg){
alert(validator);
return false
}
ajaxFn()
})
我们先封装战略类
var stratigies = {
isNonEmpty: function(value,erromsg){
if(value == ""){
return erromsg
}
},
minlength: function(value,length,erromsg){
if(value.length < length){
return erromsg
}
}
}
封装 考证(validator类)
var Validator = function(){
this.cache = [] //用来缓存
}
Validator.prototype.add = function(item,rule,erroMsg){
var arg = rule.split(":") // rule= > "isEmpty" => ["isEmpty"] || "minLength:5"=> ["minlength", “5”];
this.cache.push(function(){
var strategy = arg.shift(); // =>"isEmpty" || minLength
arg.unshift(item.value); //[value] || [value,5]
arg.push(errMsg)// [value,errMsg] || [value,5,errMsg]
return stratigies[strategy].apply(item,arg)
})
}
//start要领就是遍历这个Validator里缓存的要领并实行
Validator.prototype.start = function(){
for(var i=0;i<this.cache.length;i++){
var fn = this.cache[i];
var msg = fn() // =>最先校验,
if(msg){
return msg // 假如msg有值 就申明考证不通过,跳出轮回
}
}
}
此时,假如须要增添划定规矩 或是修正考证划定规矩,就很简朴了
我们能够在stratigies里增添战略,也能够在 提交表单的函数里,新增或许修正划定规矩
validator.addrules(form.phone,"minLength:6") =》 validator.addrules(form.phone,"minLength:10")
很蛋疼的是,对用户名推断只能一次输入一种划定规矩,假如须要加一种推断划定规矩,我就要在add一次strategy,
书中供应了进一步的拓展。
//预期
validator.addrules(form.username,[
{
"erroMsg": "不能为空",
"strategy": 'isNonEmpty'
},
{
"erroMsg": "最小为6位",
"strategy": 'minLength:6'
}
])
将战略用数组的体式格局传入validator对象里,缓存在this.cache里,只须要调解对应的add要领就能够
//old type
Validator.prototype.add = function(item,rule,erroMsg){
var arg = rule.split(":") // rule= > "isEmpty" => ["isEmpty"] || "minLength:5"=> ["minlength", “5”];
this.cache.push(function(){
var strategy = arg.shift(); // =>"isEmpty" || minLength
arg.unshift(item.value); //[value] || [value,5]
arg.push(errMsg)// [value,errMsg] || [value,5,errMsg]
return stratigies[strategy].apply(item,arg)
})
}
// new Type
Validator.prototype.add = function(item,rules){
var _this = this; //保留this指针 for轮回里的的自实行函数的this指向window,用_this修复指针
//遍历rules
for(var i = 0;i<rules.length;i++){
var rule = rules[i];
(function(rule ){
var arg = rule.strategy.split(":") // rule= > "isEmpty" => ["isEmpty"] || "minLength:5"=> ["minlength", “5”];
var errMsg = rule.errMsg;
_this.cache.push(function(){
var strategy = arg.shift(); // =>"isEmpty" || minLength
arg.unshift(item.value); //[value] || [value,5]
arg.push(errMsg)// [value,errMsg] || [value,5,errMsg]
return stratigies[strategy].apply(item,arg)
})
})(rule)
}
}