以用户为中心的 API 异常设计

设置一个元素的高度:

var elem = document.getElementById('some-id'),
     val = '200px';

elem.style.height = val; // 原生写法
YAHOO.util.Dom.setStyle(elem, 'height', val); // YUI2 写法
$(elem).height(val); // jQuery 写法

val = '200px'时,以上三种写法都能正确工作。
val = '200xx'时,以上三种写法在 IE 下都抛出异常,在非 IE 下被忽略。
val = '-200px'时,以上三种写法在 IE 下前两种抛异常,jQuery 忽略。

由于 height 值在不少使用场景下是动态计算出来的,比如淘宝宝贝详情页,就有如下代码:

YUD.setStyle(switchTrigger, 'height', viewportHeight + docScrollTop - detailTop + 'px');

在某些特定情况下,viewportHeight + docScrollTop - detailTop是负数,于是悲剧就产生了:IE 下,将会抛出异常,导致后续代码都不再执行。(这是一个真实的故事,淘宝的部分宝贝详情页,在发这篇文章之前,就因为该异常而导致部分功能不可用)

对于前端类库来说,在设计异常时,要尽可能考虑周全:

1. 异常的作用,是给程序员排查和定位错误用。对于线上代码来说,要尽可能的将异常设计为不打扰方式。比如在特定参数开启下,才会抛出或以 log 的形式输出。

2. 要特别小心浏览器自身 API 异常的不良设计。比如 IE 下对 style.height 非有效值的处理上,就不如其它浏览器。

3. 当然,该抛的异常还是得毫不犹豫抛出来。比如null.method(),所有浏览器都会告诉你错了。类库的 API 在某些场景下也需如此设计,以让开发者第一时间内发现问题。

两句话概括 API 的异常设计原则:

1. 当某个异常不会导致后续代码不可执行时,这种异常在设计时,要尽可能不打扰用户;
2. 当某个异常会严重导致后续代码不可执行并产生不可预期的隐患时,就大胆抛出来。

简言之,就是 API 设计要以用户为中心,包括页面浏览者、类库使用者和类库开发者。

Tags: , , , , , ,

真的离不开吗

下班时分和 mimiqiao 聊天,谈到一些话题,挺有意思。最近自己一直在实践,刚好总结下:

1. 不看微博,你不会丧失任何有价值的东西。身边不少同事都有 Twitter 瘾,工作一两个小时,就会忍不住上去溜达一圈。我曾经是 Twitter 重度用户,有段时间,一天不看个七八次,整个人都会若有所失。后来意识到 Twitter 的投入产出比太低,于是逐步降低查阅和更新频率。直到最近嫌翻墙麻烦,干脆转战新浪微博。新浪微博非常娱乐,基本上一亿条消息里,也许才有那么一条会对你的人生产生真正的影响。上新浪微博和看电视一样浪费时间,何苦呢?马上戒了微博,生活多了很多有价值的暗时间。微博,迟早会死掉的。就和当年的 BBS 一样,当你逐步从校园走向社会,BBS 就会成为回忆,而且仅仅是回忆了。不看微博,你不会丧失任何有价值的东西。当然,目前有不少团队和个人,实质上是把微博当推广和宣传的工具用,这是另一个故事,你知道的。

2. 每天坚持看书半个小时,可以少于半个小时,但不要超过半个小时,这样效率最高。书籍阅读,有两个极端:一是忙得完全没时间去读书,二是闲得每天能读一个小时以上。对于已工作人群,这两个极端都不利于知识的有效积累。再忙,每天半个小时,只要有意识,肯定能挤出来,这绝对比挤乳沟容易。对于已工作人群,每天读书一个小时以上,则很容易流于自我满足和自我陶醉感,而忘了去真正实践和思考。坚持阅读好书,同时要谨慎一次性长时间阅读。

3. 不少大牛,都不热衷所谓的 Web 2.0 应用。蔡学镛说自己喜欢 Web 1.0, 周爱民也如此。John Resig 最喜欢的是正式的博文和邮件讨论。Web 2.0 充满浮躁,缺少真正帮助人成长的创意。远离这些嘈杂,技术能成长更快,生活也能更恬静。

4. 读书,读好书,花大量时间去思考,花更大量的时间去实践,这是技术成长真正离不开的。Google, RSS 等网络上的一切,仅是辅助而已。

Web 仅是一个工具,并非珠宝,切忌玩椟弃珠。

Tags: , ,

parseInt 小陷阱

看代码:

alert(parseInt(0.000001));
alert(parseInt(0.0000001));

第一条语句输出 0, 第二条语句输出 1, 囧。

继续看代码:

alert(parseInt('0.000001'));
alert(parseInt('0.0000001'));

都输出 0, 这才符合预期。

查看 ECMA-262 规范,parseInt 会先调用 toString 方法。问题已逐渐清晰:

alert(0.000001);
alert(0.0000001);

第一条语句原样输出,第二条语句输出 1e-7.
继续翻查 ECMA-262 9.8.1 ToString Applied to the Number Type 一节,恍然大悟: 阅读全文 »

Tags: , ,

Array.prototype.slice

slice 可以用来获取数组片段,它返回新数组,不会修改原数组。

除了正常用法,slice 经常用来将 array-like 对象转换为 true array.

名词解释:array-like object – 拥有 length 属性的对象,比如 { 0: ‘foo’, length: 1 }, 甚至 { length: ‘bar’ }. 最常见的 array-like 对象是 arguments 和 NodeList.

查看 V8 引擎 array.js 的源码,可以将 slice 的内部实现简化为:

function slice(start, end) {
    var len = ToUint32(this.length), result = [];
    for(var i = start; i < end; i++) {
        result.push(this[i]);
    }
    return result;
}

可以看出,slice 并不需要 this 为 array 类型,只需要有 length 属性即可。并且 length 属性可以不为 number 类型,当不能转换为数值时,ToUnit32(this.length) 返回 0.
阅读全文 »

Tags: , ,

为什么不压缩 HTML

CSS 和 JavaScript 的压缩已经很成熟,各大网站都在使用。HTML 的压缩(特指去除空白字符和注释),除了 Google 等搜索页面,在其它网页上基本见不到踪迹。

原因很简单:

  1. HTML 文档中,多个空白字符等价为一个空白字符。也就是说换行等空白字符的删除是不安全的,有可能导致部分元素的样式产生差异。
  2. HTML 元素中,有一个pre, 表示 preformatted text. 里面的任何空白,都不能被删除。
  3. HTML 中有可能有 IE 条件注释。这些条件注释是文档逻辑的一部分,不能被删除。

只想到以上 3 点,可能还有其它陷进。对于动态页面来说,HTML 的压缩有可能还会增加服务器的 CPU 负担,得不偿失。

一般来说,通过 gzip 压缩已经能达到很好的效果。进一步的压缩存在陷进,除非能像 Google 一样充分测试(Google 也仅压缩了少部分核心服务的页面),否则不推荐对 HTML 进行压缩处理。

Tags: ,

Page 4 of 38« First...23456102030...Last »