無標題文檔

jQuery 如何检测浏览器及版本

如何用 Javascript 检测浏览器似乎是老生常谈的问题。根据本人的经验,使用 Javascript 检测浏览器无非使用两大类的方法。

其一,是使用使用浏览器的功能属性。比如检测浏览器是否支持 getElementById 方法就可以使用

if (document.getElementById) {
    // the method exists, so use it here
} else {
    // do something else
}

虽然这样的检测无法得知用户具体使用哪一种浏览器,不过开发者根据浏览器的功能判断是否兼容自己的代码是经得起考验的。如果关注浏览器的实际功能而不在乎它的实际身份,就可以使用这种方法。

其二,就是使用传统的 user-agent 字符串,这可能是最古老也是最流行的检测方式。虽然从技术角度上说,用户可以 更改自己的 user-agent ,但是使用它的确能获得一些有用的信息。

话说到此可能有些偏题。使用过 jQuery 的朋友都知道,使用 jQuery 本身的 brower 方法 就可以准确的判断用户在使用那种浏览器甚至是版本。好的开发库使用者都想了解其中的一些其实现机制,那么,jQuery 是如何做到这些的?

查看 jQuery 最新的源代码(版本 1.2.2) ,在第 1195 行至 1205 行,是它的判断浏览器的函数。正如你所看见的,jQuery 使用的是上述第二种方法,即使用 user-agent 判断用户的浏览器和版本。

坦白说,起先我对短短的五行代码就可以判断浏览器的种类和版本感到非常的惊奇。在 《Javascript 高级程序设计》一书 中,作者甚至使用单独的章节描述的如何使用 Javascript 判断浏览器和操作系统。但通过阅读其代码(其实并不难),我顿时有中恍然大悟的感觉。废话不多说,贴上代码。

var userAgent = navigator.userAgent.toLowerCase();

// Figure out what browser is being used
jQuery.browser = {
    version: (userAgent.match( /.+(?:rv|it|ra|ie)[\/: ]([\d.]+)/ ) || [])[1],
    safari: /webkit/.test( userAgent ),
    opera: /opera/.test( userAgent ),
    msie: /msie/.test( userAgent ) && !/opera/.test( userAgent ),
    mozilla: /mozilla/.test(userAgent)&&!/(compatible|webkit)/.test(userAgent)
};

说到这里,其实有经验的 Javascript 开发人员已经知道了其中的奥秘。是的,jQuery 使用的是正则判断浏览器的种类和版本。做得相当的漂亮!

首先它将 user-agent 统一成小写,然后使用正则逐步的匹配是哪种浏览器。有关正则方面相关的信息,可以参考这里。不过,有人肯定会怀疑这样的判断是否正确。那么我们先来看下下面四个主流浏览器的 user-agent:

Safari(Windows edition)

... AppleWebKit/523.12.9 (KHTML, like Gecko) Version/3.0 Safari/523.12.9

Opera(Opera 9.2 on Windows XP)

Opera/9.24 (Windows NT 5.1; U; zh-cn)

Mozilla(Firefox 2.0.11 on Windows XP)

... Windows NT 5.1; zh-CN; rv:1.8.1.11) Gecko/20071127 Firefox/2.0.0.11

Internet Explorer (7.0 on Windows XP)

Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)

jQuery 非常巧妙的使用各浏览器各自不同的 user-agent 特性作为判断。比如 Safari 中 「_webkit_」 是专有的、「_opera_」 也是只有 Opera 浏览器特有等等。这种验证方法可以在目前主流的浏览器上面,基本都可以准确判断。

就在这里打住了,jQuery 的确是非常优秀的 Javascript 开发框架 之一。掌握它可以为自己的开发添加不少的乐趣。我会陆续将自己阅读 jQuery 框架的心得逐一的发上来,请大家关注。

在 Javascript 类中使用 setTimeout

最近遇到了一道 Javascript 考题,内容如下:

尝试实现注释部分的 Javascript 代码,可在其他任何地方添加更多
代码(如不能实现,说明一下不能实现的原因):

var Obj = function(msg){
   this.msg = msg;
   this.shout = function(){
      alert(this.msg);
   } 

   this.waitAndShout = function(){
      // 隔五秒钟后执行上面的 shout 方法
   }
}

var testObj = new Obj("Hello,World!");
testObj.shout();

坦白的说,之前我并没有在 Javascript 类中使用 setTimeout/setInterval 的经验,所以开始就很草率的认为这是无法实现的。但是经过深思熟虑以后发现是可以实现的。退一步说,隔五秒执行某段语句是非常容易实现的。比如不考虑别的因素,题目中的函数是可以这样写:

this.waitAndShout = function(){
    setTimeout('this.shout()', 5000);
}

在运行以后,谁都会意识到 this 这个变量是无法找到的。但是这是为什么呢,很快就可以意识到,其实 setTimeout/setInterval 是 window 对象的一个方法,所以也可以写成 window.setTimeout/window.setInterval,那么上述的 this.shout() 就非常可以容易理解为什么不能执行了,因为它实际上调用的是 window.shout() 。

知道了原因以后解决起来就非常的容易了,只要将对象绑定到 window 对象下就可以(我对 Javascript 有趣的对象机制感到兴奋)。那么,上述的函数再做一个小的修改:

this.waitAndShout = function() {
    window.Obj = this;
    setTimeout('Obj.shout()', 5000);
}

这样就可以了。实际上

setTimeout('Obj.shout()', 5000);

等价于

window.setTimeout('window.Obj.shout()', 5000);

另外,之前我也想到将对象保存为数组,然后引用调用,代码如下:

function ObjectClass (property) {
    this.property = property;
    this.id = ObjectClass.cnt;
    ObjectClass.objects[ObjectClass.cnt++] = this;
    this.method = ObjectClass_method;
}

ObjectClass.cnt = 0;
ObjectClass.objects = new Array();

function ObjectClass_method () {
    setTimeout('ObjectClass.objects[' + this.id + '].method();', 5000);
}

var obj1 = new ObjectClass('feelinglucky');
obj1.method();

不过个人感觉还是上述第一种方法清晰得多。

后记,Javascript 看来的确还是很多需要谨慎对待的地方,尤其是对象机制。就犹如我 之前所说 的,Javascript 并不比其他语言要复杂,但是它也没有你想象中的简单。

PS:完成这道题目以后, Google 发现其他的兄弟早已经解决了此类的问题,比如 这里 还有 这里 ,可以对比参考一下。


更新,感谢 Sheneyan 兄弟的提醒,还有另外的一个办法就是通过 Closure(闭包) 来实现,代码如下:

var Obj = function(msg){
   this.msg = msg;
   this.shout = function() {
      alert(this.msg);
      this.waitAndShout();
   }

   var _self = this;
   this.waitAndShout = function() {
       setTimeout(function(){_self.shout()}, 5000);
   }
}

var testObj = new Obj("Hello,World!");
testObj.shout();

看来这道题已经不能再害人了 :^)

介绍几本我在看的书

又是一个周末了,但是屋外的雨还是滴滴答答地下个不停,有点心烦。整理书桌的时候发现很多本人买的书还是「新」的,真的是有点惭愧。下面我说说最近我在看的、「收藏」的几本书。

http://fleet1.footbig.com/f/00/00/0d/66/m/15/61/156161b71df07ab0656d908de31b411e-6762.jpg

本人最近主要在看的是 《Javascript 高级程序设计》《Ajax Hacks》 。这两本书我觉得非常的棒,熟读这些书可以使自己对 Javascript 能有更高一个层次的认识(不好意思,又在忽悠了)。

在《Javascript 高级程序设计》旁边还有一本 《Javascript DOM 编程艺术》 。虽然它比上述的两本书要入门些,不过主要是讲解怎样设计基于 DOM 思想的页面。建议在熟悉入门 Javascrpt 以后可以看看这本书,这本书本人多次反复熟读,真的非常的精彩。

有关用户设计方面的书籍,我主要在看 《人本界面》《用户界面设计》(第三版) 。《用户界面设计》这本书最新版似乎是第四版,内容上有改动,但是思想是一致的( 反正此书是打劫过来的 ,满足了)。但这两本书本人仅仅是当作小说在看,书中的一些理念还是需要看一段消化一段,所以一直断断续续在看,见笑了。

还有一本 《精通 CSS》 ,不要看书名而反感(其实我个人对于 Mastery 是否可以翻译成「精通」也颇有微词),这是一本好书。书中的例子都是从实际的 Hack 出发,然后再根据这些例子转入详细的原理阐述,让人感到有种豁然开朗的感觉,对于我这样的懒人来说非常的适用。

其他的一些书籍就是「Kill Time」的了。 我很喜欢几米的画册 ,尤其是喜欢《又寂寞又美好》。无聊的时候看下这些画集,可以放松下精神。还有一本 K&R 的《The C Programming Language》(第二版)影印版,这是当初浙大的师兄送给我的。

说说我接下来想看什么书吧。我一直期待能有本 《PPK On Javascript》 (电子版的早就已经有了)。PPK 此人对于 Web 开发的人员来说再熟悉不过了,所以一直想有一本印刷版作为收藏。其他的就是 《Ajax 实践》《CSS 禅意花园》 了,据说它们不错,不过我也是仅仅在书店胡乱翻了几下,没有深入。

最后,推荐在杭州的朋友一个买书的地方。就是文一路后面,登云路上面的文化商城。在它三楼有家书店专门卖计算机类的图书,最低可以打八折,其质量和数量都是较令人满意的。我的那本 《Javascript 高级程序设计》和《精通 CSS》就在他这里买的。

以前学生时代的时候在教工路上有家特价书店,那里的老板非常好,他经常会进一些我们要求的书然后成本价卖给我们,在这里感谢下他。后来可惜的是由于教工路被「整改」,特价书店所在的建筑是「违章建筑」,遂被拆。

PS: 那么多的链接 Copy 死偶了...

我的照片

嗨!我叫「明城」,八零后、码农、宁波佬,现居杭州。除了这里,同时也欢迎您关注我的 GitHubTwitterInstagram 等。

这个 Blog 原先的名字叫 Gracecode.com 、现在叫 「無標題文檔」 。 要知道作为码农取名是件很难的事情,所以不想在取名这事情上太费心思。

作为八零后,自认为还仅存点点可能不怎么被理解的幽默感,以及对平淡生活的追求和向往。 为了避免不必要的麻烦,声明本站所输出的内容以及观点仅代表个人,不代表自己所服务公司或组织的任何立场。

如果您想联系我,可以发我邮件 `echo bWluZ2NoZW5nQG91dGxvb2suY29tCg== | base64 -d`

分类

搜索

文章