一、关于功能情境
先来简单的,页面上一个“兑换礼品”的按钮,这个按钮上有如下些逻辑判断:
1. 用户是否已经登录,如果没有登录,则弹出登录框,让其执行登录操作(无刷新),登录成功后执行2;否则直接执行2. 2. 如果用户已经登录或登录成功,弹出选择礼品数目的弹框,让用户进行数目设置。
var funDLogin = function(callback) { /* ... */}, funDoNumberChange = function() { /* ... */ }; button.click(function() { if (isLogin) { //如果登录,弹框 funDoNumberChange(); } else { //如果非登录,执行登录弹框,成功后执行数目设置弹框 doLogin(function() { //登录成功的回调 funDoNumberChange(); }); } });
三、复杂的功能情境
还是那个“兑换礼品”的按钮,现在关联逻辑和判断多了点:
1. 用户是否已经登录,如果没有登录,则弹出登录框,让其执行登录操作(无刷新),登录成功后执行2;否则直接执行2. 2. 如果用户已经登录或登录成功,判断用户是否已经绑定手机,如果用户已经绑定手机,执行3;否则,弹出绑定手机的弹框,有一些绑定的Ajax操作,绑定成功后执行3; 3. 如果用户已经是登录状态,同时手机已经绑定,弹出选择礼品数目的弹框,让用户进行数目设置。
如果我们还是完全按照现实世界的经验去处理上面的功能,则就会是下面这个样子:
var funDoLogin = function(callback) { /* ... */ }, funDoBind = function(callback) { /* ... */ }, funDoNumberChange = function() { /* ... */ }; button.click(function() { if (isLogin) { //如果已经登录 if (isBind) { //如果已经绑定 //则打开数目修改弹框 funDoNumberChange(); } else { //如果未绑定 //打开绑定弹框 funDoBind(function() { //绑定成功的回调 funDoNumberChange(); }); } } else { //如果未登陆,打开登录弹框 funDoLogin(function() { if (isBind) { //如果已经绑定 //则打开数目修改弹框 funDoNumberChange(); } else { //如果未绑定 //打开绑定弹框 funDoBind(function() { //绑定成功的回调 funDoNumberChange(); }); } }); } });代码的逻辑判断结果出现了几个级别的增加。上面的代码虽然看上去有些啰嗦,但是,基本上每种情况都有一条路可以走到底,很符合我们现实世界的处理,想好出现的各种可能的情况,当问题出现的时候总能从容应对。
好吧,我想不用我说,你也会对上面裹脚布式的code有些意见的——代码冗余啰嗦。现实世界的经验有时候反映在我们程序上就不适合。
四、时间换空间
现实世界我们往往是用空间换时间。但是,在程序的世界里,时间是廉价的,用时间换空间的做法往往更合适。
到底怎么个时间换空间法呢?
很简单,“重头再来”, 具体点就是,碰到什么问题了,解决之,然后从头再来(有别于躲避之,走其他路)。
一有问题就从头再来不是很浪费时间吗?确实,时间损耗要多些,但是,对于目前的计算机而言,你一个眨眼的功夫,CUP不知奔腾了多少下了。这点时间的损耗,我们基本上可以忽略不计。我们应该把重点放在简单清晰的逻辑处理上。
OK,上面的逻辑处理如果使用“重头再来”的策略,该如何实现呢?如下:
var funDoLogin = function(callback) { /* ... */ }, funDoBind = function(callback) { /* ... */ }, funDoNumberChange = function() { /* ... */ }; button.click(function() { if (isLogin && isBind) { //如果登录同时绑定,打开修改礼品数目弹框 funDoNumberChange(); } else { if (!isLogin) { //如果没有登录,打开登录弹框 funDoLogin(function() { //登录后重新触发点击事件 button.trigger("click"); }); } else if (!isBind) { //如果没有绑定,打开绑定弹框 funDoBind(function() { //绑定后重新触发点击事件 button.trigger("click"); }); } } });上面代码红色高亮注释的部分就是“重头再来”的执行部分。我们浪费了点微不足道的时间,换去了更简单易懂的代码空间。显然,比牺牲空间的做法要划算多了。