摘要:复用性缺点增加了策略类对象的使用使用策略模式,必须先了解所有的,违反了最少知识原则参考资料设计模式之策略模式减少语句的技巧对象属性的命名规则中和代替作者以乐之名本文原创,有不当的地方欢迎指出。
说说烂大街的if/if...else...,程序中用得最多的流程判断语句。
对着曾经满屏的if/if...else...,心想能不能搞点事情,折腾点浪花浪里呀浪。
对顶着“这个需求很简单,怎么实现我不管,明天上线”的程序猿,答案必须YES。
"Write Less, Do More",学习进步的本质就是为了更有效率地偷懒。
废话说完,直接上方法汇总,让我们来一窥究竟:
switch改写if// if 版本 var a = 1; if(a > 1 && a < 5) { return 1 } else if(a > 5 && a < 10){ return 5 }else{ return 10 } // switch 改版 switch(true){ case (a > 1 && a < 5): return 1 case (a > 5 && a < 10): return 5 default: return 10 }
以上代码的switch...case...的用法实际使用不多,仅供参考。
一般case为常量时switch...case...用得较多。
选择分支较多时,建议选用switch…case可提高程序的效率,但switch...case不足的地方在于只能处理字符或者数字类型的变量,if…else更加灵活,可用于判断表达式是否成立,比如if(a+b>c),if…else的应用范围更广。
三元运算符改写if// if 版本 if (bool) { value = 1; } else { value = 2; } // 三元运算符 版本 value = bool ? 1 : 2; // 三元预算符 多个运算需要括号包裹 此处用了逗号表达式 return typeof foo === "object"?(console.log(1),1):(console.log(2),2);
优点:代码简化,更加清爽,write less
缺点:复杂的三元运算符可读性较差,需友好注释
TIPS: 三元运算符后面不能带return
// 错误用法,运算符号后不能带return bool ? return 1 : return 2;逻辑判断 and(&&)和or(||) 改写if
原理:利用逻辑判断的短路运算来实现
短路:&& 中第一个表达式为假就不会去处理第二个表达式,|| 则相反
// if为真 if (bool) { value = getYes(); } // &&改版 bool && (value = getYes()); // if为假 if (!bool) { value = getNo(); } bool || (value = getNo());
优点:代码简化,更加清爽,write less
缺点:适用于简单判断逻辑,复杂的判断运算可读性较差,需友好注释
TIPS:适用于没有else的场景, 逻辑运算符后面不能带return
// 错误用法,运算符号后不能带return boll || return true;知识点插播 —— (1)
三元运算符和逻辑运算符都有一层return作用,但不可作用于函数return语句,所以像以下这种用法都是错误的;
// 错误用法 function getResult(value) { value ? "yes" : "no"; } var result = getResult(true); // 并不会有值返回
js逻辑运算中,0/""/null/false/undefined/NaN都会判为false,其它都为true;
很多开源代码中可见if(!!attr),为什么不直接写if(attr), 其实这是一种更严谨的写法,!!attr会强制转化为boolean类型。typeof !!attr == true 比 typeof attr == true 更加严谨。
对象属性// if版本 if (a == 1) { return "one"; } else if (a == 2) { return "two"; } else if (a == 3) { return "three"; } else { return ""; } // 对象属性 改版 var ret = { 1: "one", 2: "two", 3: "three" }; return ret[a] ? ret[a] : "";
TIPS:
判断值需为确定值,如== ,其它如>=/<=/>/<不适用
条件作为对象属性,需要注意对象属性的读取方式
知识点插播 —— (2)标识符只能由字母、数字、下划线和‘$’组成
数字不可以作为标识符的首字符
通过[]操作符为对象添加属性时,属性名可以是任何字符串(包括只包含空格的字符串和空字符串);
通过.操作符为对象添加属性时,属性名必须是合法的标识符名称;
如果属性名包含非法的标识符字符,则只能采用obj[“propertyName”]的形式;
如果属性名是合法的标识符,读取时可采用obj.propertyName或obj[“propertyName”]的形式;
策略模式策略模式:定义一系列的算法,把它们一个个封装起来,目的就是将算法的使用与算法的实现分离开来
以下为常见的表单验证,用策略模式来构建,替换if...else的方式
// html// js // 策略对象 var strategies = { isNoEmpty: function (value, errorMsg) { if (value === "") { return errorMsg; } }, isNoSpace: function (value, errorMsg) { if (value.trim() === "") { return errorMsg; } }, minLength: function (value, length, errorMsg) { if (value.trim().length < length) { return errorMsg; } }, maxLength: function (value, length, errorMsg) { if (value.length > length) { return errorMsg; } }, isMobile: function (value, errorMsg) { if (!/^(13[0-9]|14[5|7]|15[0|1|2|3|5|6|7|8|9]|17[7]|18[0|1|2|3|5|6|7|8|9])d{8}$/.test(value)) { return errorMsg; } } } // 验证类 var Validator = function() { this.cache = []; } Validator.prototype.add = function(dom, rules) { var self = this; for(var i = 0, rule; rule = rules[i++];) { (function(rule) { var strategyAry = rule.strategy.split(":"); var errorMsg = rule.errorMsg; self.cache.push(function() { var strategy = strategyAry.shift(); strategyAry.unshift(dom.value); strategyAry.push(errorMsg); return strategies[strategy].apply(dom, strategyAry); }) })(rule) } }; Validator.prototype.start = function() { for(var i = 0, validatorFunc; validatorFunc = this.cache[i++];) { var errorMsg = validatorFunc(); if (errorMsg) { return errorMsg; } } }; // 调用代码 var registerForm = document.getElementById("registerForm"); var validataFunc = function() { var validator = new Validator(); validator.add(registerForm.userName, [{ strategy: "isNoEmpty", errorMsg: "用户名不可为空" }, { strategy: "isNoSpace", errorMsg: "不允许以空白字符命名" }, { strategy: "minLength:2", errorMsg: "用户名长度不能小于2位" }]); validator.add(registerForm.password, [ { strategy: "minLength:6", errorMsg: "密码长度不能小于6位" }]); validator.add(registerForm.phoneNumber, [{ strategy: "isMobile", errorMsg: "请输入正确的手机号码格式" }]); var errorMsg = validator.start(); return errorMsg; } registerForm.onsubmit = function() { var errorMsg = validataFunc(); if (errorMsg) { alert(errorMsg); return false; } }
第一个部分是一组策略类,策略类封装了具体的算法,并负责具体的计算过程;
第二个部分是环境类Context,该Context接收客户端的请求,随后把请求委托给某一个策略类;
优点:
有效避免多重条件选择语句
提供了对外开放 - 封装原则的完美支持,将方法封装在独立的strategy中,使得它们易于切换、易于理解、易于扩展。
复用性
缺点:
增加了策略类/对象的使用
使用策略模式,必须先了解所有的strategy,违反了最少知识原则
参考资料
JavaScript设计模式之策略模式
js减少if语句的技巧
js对象属性的命名规则
javascript中||和&&代替if
作者:以乐之名
本文原创,有不当的地方欢迎指出。转载请指明出处。
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/96395.html
摘要:如果一次判断的是多个元素,可以在内置的元素上使用条件指令,最终渲染的结果不会包含该元素。列表渲染也支持用代替作为分隔符,它更接近迭代器的语法的表达式支持一个可选参数作为当前项的索引。分隔符前的语句使用括号,第二项就是当前项的索引。 学习笔记:内置指令 内置指令 基本指令 v-cloak v-cloak不需要表达式,它会在Vue实例结束编译时从绑定的HTML元素上移除,经常和CSS的d...
摘要:与绑定数据绑定一个常见需求是操作元素的列表和它的内联样式。两者只能选其一对象语法我们可以传给一个对象,以动态地切换。注意不支持语法。相比之下,简单得多元素始终被编译并保留,只是简单地基于切换。这意味着将分别重复运行于每个循环中。 vue Class 与 Style 绑定 数据绑定一个常见需求是操作元素的 class 列表和它的内联样式。因为它们都是属性,我们可以用 v-bind 处理...
摘要:最近的技术项目里大量用到了需要修改源文件代码的需求,也就理所当然的用到了及其插件开发。在这里我要推荐一款实现了这些标签的插件,建议在你的项目中加入这个插件并用起来,不用再艰难的书写三元运算符,会大大提升你的开发效率。具体可以参见插件手册。 最近的技术项目里大量用到了需要修改源文件代码的需求,也就理所当然的用到了Babel及其插件开发。这一系列专题我们介绍下Babel相关的知识及使用。 ...
摘要:彻底解决嵌套问题开发过程中常因为过多导致代码融于,难以阅读,今天就我们就一起来解决这个问题,让代码更优美,维护更方便,接盘侠更开心有函数根据传入水果类型返回颜色,代码如下写法一写法二把同类放到一个中数组筛选内多条件处理更早丢出不符合条件的资 彻底解决if else嵌套问题 开发过程中常因为if else过多导致代码融于,难以阅读,今天就我们就一起来解决这个问题,让代码更优美,维护更方便...
摘要:基于,可以在中导入模板。利用对象函数替换对象或者运行函数支持点语法可以对象等属性值使用时,直接标签引入文件。模块会自动匹配相应的数值,对象或者是函数。也可以单独建立一个模板,或者可以用来唯一确定一个模板,是固定写法,不可或缺。 前言:常用的末班引擎有很多,但写法都大同小异。handlebars.js就是一个纯JS库,因此你可以向其他脚本一样用script包起来。调用内部封装好的功能。 ...
阅读 3350·2021-10-13 09:40
阅读 2586·2021-10-08 10:17
阅读 3988·2021-09-28 09:45
阅读 920·2021-09-28 09:35
阅读 1804·2019-08-30 10:51
阅读 2897·2019-08-26 12:11
阅读 1643·2019-08-26 10:41
阅读 3089·2019-08-23 17:10