你不知道的JavaScript--Item36 客户端检测技术_${item

//判断document是否支持getelementById方法
if(document.getElementById){
return document.getElementById();
}


两个重要的概念:


* 第一个概念是先检测达成目的的最常用的特性。先检测最常用的特性,可以保证代码最优化,因为在多数情况下都可以避免测试多个条件。
* 第二个概念是必须测试实际要用到的特性。一个特性存在,不一定意味着另一个特性也存在。


### 可靠的能力检测


如果判断某个对象是否支持排序方法,可以使用操作符typeof



//只检测了是否存在相应的方法
function isSortable(object){
return !!object.sort;
}
var result= isSortable({sort:true});


在可能的情况下,尽量使用typeof进行能力检测。



function isSortable(object){
return typeof object.sort == "function ";
}


但是并不是所有浏览器都会返回的值都合理。大部分浏览器在检测到document.createElement存在时,都会返回ture,但是在IE8及之前的IE版本会返回false。



function hasCreateElement(){
return typeof document.createElement =="function ";
}


IE8之前的版本返回false.因为DOM对象是宿主对象,是通过COM而不是JScript实现的,document.createElement()函数是一个COM对象。IE9已更正。



var xhr=new ActiveXObject(“Microsoft.XMLHttp”);
if(xhr.open){ //error
//TO-DO
}


直接把函数属性访问会导致JS错误。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


检测某个或某几个特性并不能够确定浏览器。实际上,根据浏览器不同将能力组合起来是更可取的方式。如果知道自己的应用程序需要使用某些特定的浏览器特性,那么最好是一次性检测所有相关特性,而不要分别检测。



//确定浏览器是否支持 Netscape 风格的插件
var hasNSPlugins = !!(navigator.plugins && navigator.plugins.length );

//确定浏览器是否具有 DOM1 级规定的能力
var hasDOM1 = !!(document.getElementById && document.createElement
&& document.getElementByTagName);


## 2. 怪癖检测 Quirkys Detection


目标识别浏览器特殊的行为,与能力检测不同,是想知道浏览器存在的什么缺陷.运行一小段代码,以确定某一特性不能正常工作.


“怪癖”都是个别浏览器所独有的,而且通常被归为 bug。由于检测“怪癖”涉及运行代码,因此建议仅检测那些对你有直接影响的“怪癖”,而且最好在脚本一开始就执行此类检测,以便尽早解决问题。


例如,IE中存在的一个 bug ,即如果某个实例属性与标记为 [[DontEnum]] 的某个原型属性同名,那么该实例属性将不会出现在 fon-in 循环当中。可以使用如下代码来检测这种“怪癖”:



var hasDontEnumQuirk = function(){
var o = { toString : function(){}};

for( var prop in o){
    if( prop == "toString"){
        return false;
    }
}
return true;

}();


## 3. 用户代理检测


  争议最大的一种客户端检测技术。用户代理检测通过检测用户代理字符串来确定实际使用的浏览器。在每一次HTTP请求过程中,用户代理字符串是作为响应首部发送的,而该字符串可以通过 JavaScript 的 navigator.userAgent 属性访问。在服务器端,通过检测用户代理字符串来确定用户使用的浏览器是一种常用而且广为接受的做法。而在客户端,用户代理检测一般被当作一种万不得已才使用的做法,其优先级排在能力检测和怪癖检测之后。 


### 3.1 识别呈现引擎


  确切的知道浏览器的名字和版本号不如确定他们使用的是什么呈现引擎。如果Firefox、Camino 和 Netsacpe 都使用相同版本的 Gecko ,那么他们一定支持相同的特性。类似的,不管是什么浏览器,只要它跟 Safari 3 使用的是同一个版本的 WebKit,那么该浏览器也就跟 Safari 3 具备同样的功能。因此,我们需要编写的脚本将主要检测五大呈现引擎: IE、Gecko、WebKit、KHTML 和 Opera1。


  注1:现在Opera 和 Chrome将采用基于WebKit开发自主渲染引擎Blink。


  模块增强模式封装检测脚本。



var client = function(){

//呈现引擎
var engine = {
    ie : 0,
    gecko : 0,
    webkit : 0,
    khtml : 0,
    opera : 0,

    //具体的版本号
    ver : null
};

//再次检测呈现引擎、平台和设备
return {
    engine : engine
};

}();


  如果检测到那个呈现引擎,就以浮点数值形式将该引擎的版本号写入相应的属性。而呈现引擎的完整版本是一个字符串,则被写入ver属性。



if(client.engine.ie){ //如果是IE ,engine.ie的值应大于0
//针对IE
} else if (client.engine.gecko > 1.5) {
if(client.engine.ver == “1.8.1”){
//to-do
}

}


  检测到一个呈现引擎后,其 client.engine 中对应的属性将被设置成一个大于 0 的值,该值可以转换成布尔值的 true。这样就可以在 if 语句中检测相应的属性,以确定当前使用的呈现引擎,连具体的版本号都不需要考虑。鉴于每个属性都包含一个浮点数值,因此有可能丢失某些版本信息。例如,将字符串”1.8.1”传入 parseFloat() 后悔得到数值 1.8。不过,在必要的时候,可以检测 ver 属性,该属性中保存着完整的版本信息。


  **正确的识别呈现引擎关键是检测顺序要正确。**


  首先应该检测的是 Opera,因为它的用户代理字符串可能完全模仿其他浏览器。



//Opera 5起支持window.opera对象
if ( window.opera ){
engine.ver = window.opera.version(); //Opera 7.6起返回浏览器版本字符串
engine.opera = parseFloat( engine.ver );
}


  其次检测 WebKit.因为WebKit的用户代理字符串包含“Gecko”和“KHTML”,若先检测他们,可能会出现错误的结论。



//AppleWebKit独一无二
var ua = navigator.userAgent;

if ( window.opera ){
engine.ver = window.opera.version();
engine.opera = parseFloat( engine.ver );
} else if ( /AppleWebKit/(\S+)/.test(ua)){
engine.ver = RegExp[“$1”];
engine.webkit = parseFloat(engine.ver);
}


  仅供参考,不保证精确。 


  接下来测试 KHTML。KHTML的用户代理字符串包含“Gecko”,所以在排除KHTML之前是无法正确检测基于Gecko的浏览器。Konqueror 3.1及更早的版本不包含KHTML的版本,要使用Konqueror的版本来替代。



var ua = navigator.userAgent;

if ( window.opera ){
engine.ver = window.opera.version();
engine.opera = parseFloat( engine.ver );
} else if ( /AppleWebKit/(\S+)/.test(ua)){
engine.ver = RegExp[“$1”];
engine.webkit = parseFloat(engine.ver);
} else if ( /KHTML/(\S+)/.test(ua) || /Konqueror/([^;]+)/.test(ua)){
engine.ver = RegExp[“$1”];
engine.khtml = parseFloat(engine.ver);
}


  下面我们就可以准确的检测Gecko。Gecko的版本号位于字符串“rv:”与一个闭括号之间,还要查找“Gecko/”后的8个数字。



//Windows XP 下的 Firefox 2.0.0.11 :
Mbzilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.11) Gecko/20071127 Firefox/2.0.




---



var ua = navigator.userAgent;

if ( window.opera ){
engine.ver = window.opera.version();
engine.opera = parseFloat( engine.ver );
} else if ( /AppleWebKit/(\S+)/.test(ua)){
engine.ver = RegExp[“$1”];
engine.webkit = parseFloat(engine.ver);
} else if ( /KHTML/(\S+)/.test(ua) || /Konqueror/([^;]+)/.test(ua)){
engine.ver = RegExp[“$1”];
engine.khtml = parseFloat(engine.ver);
} else if ( /rv:([^)]+)) Gecko/\d{8}/.test(ua)){
engine.ver = RegExp[“$1”];
engine.gecko = parseFloat(engine.ver);
}


最后是IE.IE版本号位于MSIE的后面。



var ua = navigator.userAgent;

if ( window.opera ){
engine.ver = window.opera.version();
engine.opera = parseFloat( engine.ver );
} else if ( /AppleWebKit/(\S+)/.test(ua)){
engine.ver = RegExp[“$1”];
engine.webkit = parseFloat(engine.ver);
} else if ( /KHTML/(\S+)/.test(ua) || /Konqueror/([^;]+)/.test(ua)){
engine.ver = RegExp[“$1”];
engine.khtml = parseFloat(engine.ver);
} else if ( /rv:([^)]+)) Gecko/\d{8}/.test(ua)){
engine.ver = RegExp[“$1”];
engine.gecko = parseFloat(engine.ver);
} else if (/MSIE ([^;]+)/.test(ua)){
engine.ver = browser.ver = RegExp[“$1”];
engine.ie = browser.ie = parseFloat(engine.ver);
}


### 3.2.识别浏览器


  识别了浏览器的呈现引擎就足以为我们采取正确的操作提供依据了。可是,只有呈现引擎还不能够说明存在所需的JavaScript功能。相同内核的浏览器的JavaScript有可能引擎不一样:safari 和chrome。



var client = function(){
//呈现引擎

var engine = {
    ie : 0,
    gecko : 0,
    webkit : 0,
    khtml : 0,
    opera : 0,

    //具体的版本号
    ver : null
};

var browser = {
    //浏览器
    ie : 0,
    firefox : 0,
    konq : 0,
    opera : 0,
    chrome : 0,
    safari : 0,

    //具体的版本
    ver : null
};

算法

  1. 冒泡排序

  2. 选择排序

  3. 快速排序

  4. 二叉树查找: 最大值、最小值、固定值

  5. 二叉树遍历

  6. 二叉树的最大深度

  7. 给予链表中的任一节点,把它删除掉

  8. 链表倒叙

  9. 如何判断一个单链表有环

由于篇幅限制小编,pdf文档的详解资料太全面,细节内容实在太多啦,所以只把部分知识点截图出来粗略的介绍,每个小节点里面都有更细化的内容!

chrome : 0,
safari : 0,

    //具体的版本
    ver : null
};

算法

  1. 冒泡排序

  2. 选择排序

  3. 快速排序

  4. 二叉树查找: 最大值、最小值、固定值

  5. 二叉树遍历

  6. 二叉树的最大深度

  7. 给予链表中的任一节点,把它删除掉

  8. 链表倒叙

  9. 如何判断一个单链表有环

    [外链图片转存中…(img-TXmDiYNs-1714549175420)]

由于篇幅限制小编,pdf文档的详解资料太全面,细节内容实在太多啦,所以只把部分知识点截图出来粗略的介绍,每个小节点里面都有更细化的内容!

开源分享:【大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值