倒着想问题,其实就是一种思维方式,即逆向思维,其实平时我们都会用这种思维方式去想问题,只是可能没注意到。这几天写程序时,特别注意了一下逆向思维的应用,发现它确实是一种非常好用的思维方式,能解决很多问题,结合几个实例,总结总结。
先看一个在地图上加蒙板的例子。

我要实现一个功能,当鼠标在地图上拖动时,会拖出一个矩形框,如上图中的5部分所示。让我们想想应该怎么实现?5部分是由1、2、3、4四个div围成的,我们是不是可以先确定好1、2、3、4这四个div,然后自然就形成了5部分呢?答案当然是肯定的,我们只要规定好1、2、3、4的top、left、width、height四个属性,就能确定这四个div,而它们的top、left、width、height属性,我们都可以通过鼠标的坐标来得到。当鼠标按下时,我们可以确定1、2的top、left、width、height,还有3的left,width。当拖动完成抬起鼠标时,剩下的3,4也可以确定了。这样,我们就实现了想要的效果。
这样做不管从理论上,还是实践上讲都没有问题,但是现实往往是残酷的。刚才这种情况,我们是从左上角开始拖动,会不会有人从右上角开始拖呢?答案也是肯定的,会,不但会从右上角拖,从右下角,左下角拖的也有,要好能拖出朵花来,我毫不怀疑有人会下大功夫拖出一朵玫瑰花来。如果不确定从哪儿开始拖,我们就不知道到底先确定哪几个div,只能分四种情况考虑,这样代码就麻烦了。
作为一个合格的社会主义新中国的IT民工,我决不允许这样的代码出现。我们不妨把问题倒过来想想。刚才是先确定的1、2、3、4四个div,由它们围成一个确定的5,那要是先确定5,再通过它去确定1、2、3、4呢?理论上是可行的。通过5的top,我们可以确定1;通过5的left、top,我们可以确定2;通过5的left、height,我们可以确定3;通过5的top、height、width,我们可以确定4。理论上可行,实践上我们也可以实现,5的top、left属性,永远都等于两次鼠标坐标变化时小的那个,5的width、height属性,永远都等于两次鼠标变化时差的绝对值。ok,搞定,简单多了吧。
再来看一个例子。
我给公司首页加输入的自动提示时,曾经考虑过不在页面里加一个定时器,而是采用射雕博客里的这篇文章里的方案三,当输入框里的文字发生变化,就使用oninput或onpropertychange事件发送请求。这里有个需要注意的地方,当用户输入过快时,这些不必要的请求是不应该被发送出去的,以防止服务器负担过重。不过这就有个问题,怎么确定到底发不发请求呢?当时射雕(也就是淘宝的正淳)教我设定一个时间阈值,判断两次文字发生变化的时间间隔,当时间间隔小于这个阈值时,就不发送请求,否则就发送。但这样做其实是不可行的,因为最后一次输入后就再也没有输入了,就得不到一个时间间隔,从而就不知道到底发送不发送这次请求。当时我也没想出来,就采用了像现在baidu,google等的方式,加一个定时器。
后来我又要实现一个功能,用户拖动地图时,地图中心点发生变化,这时我要用ajax将中心点的经纬度发给一个php程序处理,但如果用户拖动过快,即用户还没有确定要看哪部分地图,那么就不发送请求。上面那种情况同样的问题,我无法确定最后一次请求发送还是不发送。
让我们认真的想想。正常的思路是,默认不发送请求,当时间间隔大于某个阈值时,就发送请求。那么我们可不可以倒过来呢?默认发送请求,当时间间隔小于某个阈值,就把发送请求的动作取消。理论上没啥问题,现实中我们也可以实现,js有个东西叫setTimeout不是。于是乎,上面两个问题都搞定了,来看看地图的效果。
以上,我们可以看出逆向思维确实是可以帮助我们在程序开发的过程中解决许多难题的,当我们遇到难已解决的问题时,不妨试试。最后,我想说的是,在解决问题时,我们应该让脑袋灵活点,一条思路走不通,我们可以倒着、侧着,站着、躺着、走着,全方位、立体式、多角度的思考问题。