能力检测简述 能力测试的方法有哪些
yuyutoo 2024-10-18 12:12 2 浏览 0 评论
最常用也最为人们广泛接受的客户端检测形式是能力检测(又称特性检测)。能力检测的目标不是识别特定的浏览器,而是识别浏览器的能力。采用这种方式不必顾及特定的浏览器如何如何,只要确定浏览器支持特定的能力,就可以给出解决方案。能力检测的基本模式如下:
if (object.propertyInQuestion){
//使用object.propertyInQuestion
}
举例来说,IE5.0之前的版本不支持document.getElementsById()这个DOM方法。尽管可以使用非标准的document.all属性实现相同的目的,但IE的早期版本中确实不存在document.getElementsById()。于是,也就有了类似下面的能力检测代码:
function getElement(id){
if (document.getElementById){
return document.getElementById(id);
} else if (document.all){
return document.all[id];
} else {
throw new Error("No way to retrieve element!");
}
}
这里的getElement()函数的用途是返回具有给定ID的元素。因为document.getElementById()是实现这一目的的标准方式,所以一开始就测试了这个方法。如果该函数存在(不是未定义),则使用该函数。否则,就要继续检测document.all是否存在,如果是,则使用它。如果上述两个特性都不存在(很有可能),则创建并抛出错误,表示这个函数无法使用。
要理解能力检测,首先必须理解两个重要的概念。如前所述,第一个概念就是先检测达成目的的最常用的特性。对前面的例子来说,就是要先检测document.getElementById(),后检测document.all。先检测最常用的特性可以保证代码最优化,因为在多数情况下都可以避免测试多个条件。
第二个重要的概念就是必须测试实际要用到的特性。一个特性存在,不一定意味着另一个特性也存在。来看一个例子:
function getWindowWidth(){
if (document.all){ //假设是IE
return document.documentElement.clientWidth; //错误的用法!!!
} else {
return window.innerWidth;
}
}
这是一个错误使用能力检测的例子。getWindowWidth()函数首先检查document.all是否存在,如果是则返回document.documentElement.clientWidth。第8章曾经讨论过,IE8及之前版本确实不支持window.innerWidth属性。但问题是document.all存在也不一定表示浏览器就是IE。实际上,也可能是Opera;Opera支持document.all,也支持window.innerWidth。
9.1.1 更可靠的能力检测
能力检测对于想知道某个特性是否会按照适当方式行事(而不仅仅是某个特性存在)非常有用。上一节中的例子利用类型转换来确定某个对象成员是否存在,但这样你还是不知道该成员是不是你想要的。来看下面的函数,它用来确定一个对象是否支持排序。
//不要这样做!这不是能力检测——只检测了是否存在相应的方法
function isSortable(object){
return !!object.sort;
}
这个函数通过检测对象是否存在sort()方法,来确定对象是否支持排序。问题是,任何包含sort属性的对象也会返回true。
var result = isSortable({ sort: true });
检测某个属性是否存在并不能确定对象是否支持排序。更好的方式是检测sort是不是一个函数。
//这样更好:检查sort是不是函数
function isSortable(object){
return typeof object.sort == "function";
}
这里的typeof操作符用于确定sort的确是一个函数,因此可以调用它对数据进行排序。
在可能的情况下,要尽量使用typeof进行能力检测。特别是,宿主对象没有义务让typeof返回合理的值。最令人发指的事儿就发生在IE中。大多数浏览器在检测到document.createElement()存在时,都会返回true。
//在IE8及之前版本中不行
function hasCreateElement(){
return typeof document.createElement == "function";
}
在IE8及之前版本中,这个函数返回false,因为typeof document.createElement返回的是"object",而不是"function"。如前所述,DOM对象是宿主对象,IE及更早版本中的宿主对象是通过COM而非JScript实现的。因此,document.createElement()函数确实是一个COM对象,所以typeof才会返回"object"。IE9纠正了这个问题,对所有DOM方法都返回"function"。
关于typeof的行为不标准,IE中还可以举出例子来。ActiveX对象(只有IE支持)与其他对象的行为差异很大。例如,不使用typeof测试某个属性会导致错误,如下所示。
//在IE中会导致错误
var xhr = new ActiveXObject("Microsoft.XMLHttp");
if (xhr.open){ //这里会发生错误
//执行操作
}
像这样直接把函数作为属性访问会导致JavaScript错误。使用typeof操作符会更靠谱一点,但IE对typeof xhr.open会返回"unknown"。这就意味着,在浏览器环境下测试任何对象的某个特性是否存在,要使用下面这个函数。
//作者:Peter Michaux
function isHostMethod(object, property) {
var t = typeof object[property];
return t=='function' ||
(!!(t=='object' && object[property])) ||
t=='unknown';
}
可以像下面这样使用这个函数:
result = isHostMethod(xhr, "open"); //true
result = isHostMethod(xhr, "foo"); //false
目前使用isHostMethod()方法还是比较可靠的,因为它考虑到了浏览器的怪异行为。不过也要注意,宿主对象没有义务保持目前的实现方式不变,也不一定会模仿已有宿主对象的行为。所以,这个函数——以及其他类似函数,都不能百分之百地保证永远可靠。作为开发人员,必须对自己要使用某个功能的风险作出理性的估计。
要想深入了解围绕JavaScript中能力检测的一些观点,请参考Peter Michaux的文章“Feature Detection: State of the Art Browser Scripting”,网址为http://peter.michaux.ca/articles/feature-detection-state-of-the-art-browser-scripting。
9.1.2 能力检测,不是浏览器检测
检测某个或某几个特性并不能够确定浏览器。下面给出的这段代码(或与之差不多的代码)可以在许多网站中看到,这种“浏览器检测”代码就是错误地依赖能力检测的典型示例。
//错误!还不够具体
var isFirefox = !!(navigator.vendor && navigator.vendorSub);
//错误!假设过头了
var isIE = !!(document.all && document.uniqueID);
这两行代码代表了对能力检测的典型误用。以前,确实可以通过检测navigator.vendor和navigator.vendorSub来确定Firefox浏览器。但是,Safari也依葫芦画瓢地实现了相同的属性。于是,这段代码就会导致人们作出错误的判断。为检测IE,代码测试了document.all和document.uniqueID。这就相当于假设IE将来的版本中仍然会继续存在这两个属性,同时还假设其他浏览器都不会实现这两个属性。最后,这两个检测都使用了双逻辑非操作符来得到布尔值(比先存储后访问的效果更好)。
实际上,根据浏览器不同将能力组合起来是更可取的方式。如果你知道自己的应用程序需要使用某些特定的浏览器特性,那么最好是一次性检测所有相关特性,而不要分别检测。看下面的例子。
//确定浏览器是否支持Netscape风格的插件
var hasNSPlugins = !!(navigator.plugins && navigator.plugins.length);
//确定浏览器是否具有DOM1级规定的能力
var hasDOM1 = !!(document.getElementById && document.createElement &&
document.getElementsByTagName);
CapabilitiesDetectionExample01.htm
以上例子展示了两个检测:一个检测浏览器是否支持Netscapte风格的插件;另一个检测浏览器是否具备DOM1级所规定的能力。得到的布尔值可以在以后继续使用,从而节省重新检测能力的时间。
在实际开发中,应该将能力检测作为确定下一步解决方案的依据,而不是用它来判断用户使用的是什么浏览器。
想要了解更多Java基础知识,可以点击评论区链接和小编一起学习java吧,此视频教程为初学者而著,零基础入门篇!给同学们带来全新的Java300集课程啦!java零基础小白自学Java必备优质教程_手把手图解学习Java,让学习成为一种享受_哔哩哔哩_bilibili
相关推荐
- MyBatis的SQL执行流程不清楚?看完这一篇就够了
-
推荐学习真香警告!Alibaba珍藏版mybatis手写文档,刷起来...
- SpringBoot开发必备!49个内置工具类,让你的代码效率翻倍!
-
作为一名Java开发者,你是否经常为字符串处理、文件操作、数据验证等重复性代码头疼?SpringBoot的武器库里藏着...
- C# 基于命名管道(Named Pipes) 的进程间通信(IPC)
-
基于命名管道(NamedPipes)的进程间通信(IPC),用于在同一台机器不同进程之间进行高效、可靠的数据传输,是一种基于消息或流的通信机制。管道有一个唯一的名称,客户端和服务器端通过名称连接到...
- 十年之重修MyBatis原理(mybatis方法重载)
-
弱小和无知并不是生存的障碍,傲慢才是。--------面试者...
- C#串口通信(c#串口通信界面)
-
串口通信(SerialCommunications)是指外设和计算机间通过数据信号线、地线等按位(bit)进行传输数据的一种通信方式,属于串行通信方式,能够实现远距离通信,长度可达1200米。尽管比...
- C#中使用命名管道进行进程通信的实例
-
1新建解决方案NamedPipeExample...
- 继GitHub之后 OpenAI为ChatGPT推出OneDrive和SharePoint连接器
-
上周,OpenAI宣布推出ChatGPT的GitHub连接器,允许用户对其源代码库进行深入研究。将GitHub与ChatGPT连接后,用户可以提出问题,深度研究代理将读取和搜索存储库的...
- Power BI:如何在SharePoint中嵌入Power BI报告?
-
问题描述:今天业务同事来询问如何才能将自己开发的PowerBI报告嵌入团队使用的SharePoint页面中,以更直观地和团队成员分享可视化报告。(SharePoint是微软推出的可以用来存储、整理、...
- O365(世纪互联)SharePoint 之调查列表简单介绍
-
前言SharePoint中为了提供了很多开箱即用的应用程序,比如调查列表就是其中之一,同样,在O365版本里(国际版和世纪互联版本均可),也有这样的调查列表可以供我们使用,而使用起来非常方便和快速,就...
- 制作Excel电子表格必备的:Excel 2021 mac中文版
-
MicrosoftExcel2021forMac是一款运行在Mac平台上的办公软件,OfficeExcel2021forMac中文版是办公必不可少的软件,主要用于制作电子表格等,这里带...
- 微软SharePoint新特性:能以邮件方式向目标发送新闻内容
-
IT之家8月30日消息,微软今天发布新闻稿,宣布为SharePoint服务引入新特性,允许企业将新闻动态转换为电子邮件,并以时事通讯、安全公告、警告等主题发送给感兴趣的用户。微软在新闻稿中...
- 在Access中创建Sharepoint列表的链接表
-
在Access中提供了一个DoCmd.TransferSharePointList方法,一行代码就可以搞定。使用TransferSharePointList方法从SharePointFoun...
- BBC推荐:12月最值得一看的5部电影 Five films to watch in December
-
年终岁末,还有哪些精彩电影在等着我们呢?迪士尼的《欢乐满人间2》绝对是合家欢电影的首选,超级英雄迷们将能看到索尼动画《蜘蛛侠:平行宇宙》,福尔摩斯的粉丝们千万别错过《福尔摩斯与华生》。还有朱莉亚·罗伯...
- 基于锂离子电池的电池荷电状态 (SOC) 和运行健康状态 (SOH) 估计技术
-
简介基于锂离子(Li-ion)电池单元的电池组广泛用于各种应用,例如:混合动力汽车(HEV)、电动汽车(EV)、可供日后使用的再生能源储存以及用于各种目的(电网稳定性、调峰和再生能源时移等)的...
- 深入解析电池充电状态 (SOC) 和运行状态 (SOH) 估计技术
-
基于锂离子(Li-ion)电池单元的电池组广泛用于各种应用,例如:混合动力汽车(HEV)、电动汽车(EV)、可供日后使用的再生能源储存以及用于各种目的(电网稳定性、调峰和再生能源时移等)的电网...
你 发表评论:
欢迎- 一周热门
-
-
前端面试:iframe 的优缺点? iframe有那些缺点
-
带斜线的表头制作好了,如何填充内容?这几种方法你更喜欢哪个?
-
漫学笔记之PHP.ini常用的配置信息
-
推荐7个模板代码和其他游戏源码下载的网址
-
其实模版网站在开发工作中很重要,推荐几个参考站给大家
-
[干货] JAVA - JVM - 2 内存两分 [干货]+java+-+jvm+-+2+内存两分吗
-
正在学习使用python搭建自动化测试框架?这个系统包你可能会用到
-
织梦(Dedecms)建站教程 织梦建站详细步骤
-
【开源分享】2024PHP在线客服系统源码(搭建教程+终身使用)
-
2024PHP在线客服系统源码+完全开源 带详细搭建教程
-
- 最近发表
-
- MyBatis的SQL执行流程不清楚?看完这一篇就够了
- SpringBoot开发必备!49个内置工具类,让你的代码效率翻倍!
- C# 基于命名管道(Named Pipes) 的进程间通信(IPC)
- 十年之重修MyBatis原理(mybatis方法重载)
- C#串口通信(c#串口通信界面)
- C#中使用命名管道进行进程通信的实例
- 继GitHub之后 OpenAI为ChatGPT推出OneDrive和SharePoint连接器
- Power BI:如何在SharePoint中嵌入Power BI报告?
- O365(世纪互联)SharePoint 之调查列表简单介绍
- 制作Excel电子表格必备的:Excel 2021 mac中文版
- 标签列表
-
- mybatis plus (70)
- scheduledtask (71)
- css滚动条 (60)
- java学生成绩管理系统 (59)
- 结构体数组 (69)
- databasemetadata (64)
- javastatic (68)
- jsp实用教程 (53)
- fontawesome (57)
- widget开发 (57)
- vb net教程 (62)
- hibernate 教程 (63)
- case语句 (57)
- svn连接 (74)
- directoryindex (69)
- session timeout (58)
- textbox换行 (67)
- extension_dir (64)
- linearlayout (58)
- vba高级教程 (75)
- iframe用法 (58)
- sqlparameter (59)
- trim函数 (59)
- flex布局 (63)
- contextloaderlistener (56)