關鍵要點
- JavaScript 的特性檢測(測試程序員想要使用的特性)並不總是可靠的。例如,在 Internet Explorer 中測試 ActiveXObject 以進行 Ajax 請求、映射到 DOM 屬性的 HTML 屬性以及對用戶行為的假設(例如檢測觸摸設備)等。
- 當特性檢測失敗時,有時需要採用瀏覽器檢測。但是,建議使用專有對象測試而不是 navigator 信息,並將其用於排除瀏覽器而不是包含瀏覽器。
- 在實現瀏覽器檢測時,務必極其小心。始終首先假設完全符合特性測試,只有在知道某個特性無法按預期工作時才求助於瀏覽器檢測。此外,用於對象和特性測試的語法會影響檢測的成功率,因此選擇正確的語法至關重要。
曾經,瀏覽器檢測是 JavaScript 程序員的看家本領。如果我們知道某些功能在 IE5 中有效但在 Netscape 4 中無效,我們會測試該瀏覽器並相應地修改代碼。例如:
if (navigator.userAgent.indexOf('MSIE 5') != -1) { // 我们认为此浏览器是 IE5 }
但是,當我第一次加入這個行業時,軍備競賽就已經開始了!供應商正在向用戶代理字符串添加額外的值,因此它們看起來像是其競爭對手的瀏覽器,也是它們自己的瀏覽器。例如,這是 Mac 版 Safari 5:
<code>Mozilla/5.0 (Macintosh; Intel Mac OS X 10_6_8) AppleWebKit/534.59.10 (KHTML, like Gecko) Version/5.1.9 Safari/534.59.10</code>
這將匹配對“Safari”、“Webkit”以及“KHTML”(Webkit 基於的Konqueror 代碼庫)的測試;但它也匹配“Gecko”(這是Firefox 的渲染引擎),當然還有“Mozilla ”(由於歷史原因,幾乎每個瀏覽器都聲稱自己是Mozilla)。
添加所有這些值的目的是規避瀏覽器檢測。如果腳本假設只有 Firefox 才能處理特定功能,否則可能會排除 Safari,即使它可能也能工作。別忘了用戶自己可以更改他們的用戶代理——我曾經將我的瀏覽器設置為識別為“Googlebot/1.0”,這樣我就可以訪問網站所有者認為僅供抓取的內容!
因此,隨著時間的推移,這種瀏覽器檢測已成為一個不可能解開的亂麻,並且在很大程度上已不再使用,取而代之的是更好的東西——特性檢測。
特性檢測只是測試我們想要使用的特性。例如,如果我們需要getBoundingClientRect
(獲取元素相對於視口的位置),那麼重要的是瀏覽器是否支持它,而不是它是哪個瀏覽器;因此,與其測試受支持的瀏覽器,不如測試特性本身:
if (typeof document.documentElement.getBoundingClientRect != "undefined") { // 浏览器支持此函数 }
不支持該函數的瀏覽器將返回“undefined”類型,因此不會通過條件。無需在任何特定瀏覽器中測試腳本,我們就知道它要么正確工作,要么靜默失敗。
或者我們……?
但事實是——特性檢測也不是完全可靠的——有時它會失敗。因此,讓我們現在看看一些示例,看看我們可以做些什麼來解決每個案例。
ActiveX 對象
也許特性檢測失敗最著名的例子是測試 ActiveXObject 以在 Internet Explorer 中進行 Ajax 請求。
ActiveX 是後期綁定對象的示例,其實際意義是您無法知道它是否受支持直到您嘗試使用它。因此,如果用戶禁用了 ActiveX,則以下代碼將引發錯誤:
if (navigator.userAgent.indexOf('MSIE 5') != -1) { // 我们认为此浏览器是 IE5 }
要解決此問題,我們需要使用異常處理——嘗試實例化對象,捕獲任何失敗,並相應地處理它:
<code>Mozilla/5.0 (Macintosh; Intel Mac OS X 10_6_8) AppleWebKit/534.59.10 (KHTML, like Gecko) Version/5.1.9 Safari/534.59.10</code>
映射到 DOM 屬性的 HTML 屬性
屬性映射通常用於測試與 HTML5 屬性一起使用的 API 的支持。例如,通過查找可拖動屬性來檢查具有 [draggable="true"]
的元素是否支持拖放 API:
if (typeof document.documentElement.getBoundingClientRect != "undefined") { // 浏览器支持此函数 }
這裡的問題是 IE8 或更早版本會自動將所有HTML 屬性映射到 DOM 屬性。這就是為什麼 getAttribute
在這些舊版本中如此混亂的原因,因為它根本不返回屬性,而是返回 DOM 屬性。
這意味著如果我們使用已經具有屬性的元素:
if (typeof window.ActiveXObject != "undefined") { var request = new ActiveXObject("Microsoft.XMLHTTP"); }
那麼即使它們不支持,IE8 或更早版本也會返回 true
用於 ("draggable" in element)
。
屬性可以是任何內容:
if (typeof window.ActiveXObject != "undefined") { try { var request = new ActiveXObject("Microsoft.XMLHTTP"); } catch (ex) { request = null; } if (request !== null) { //... 我们有一个请求对象 } }
但結果將相同——IE8 或更早版本將返回 true
用於 ("nonsense" in element)
。
在這種情況下,解決方案是使用不具有該屬性的元素進行測試,最安全的方法是使用創建的元素:
if ("draggable" in element) { // 浏览器支持拖放 }
對用戶行為的假設
您可能已經看到使用以下代碼來檢測觸摸設備:
<div draggable="true"> ... </div>
大多數觸摸設備在觸發點擊事件之前會實現人工延遲(通常約為 300 毫秒),這是為了避免在雙擊元素的同時也點擊它們。但這會使應用程序感覺遲緩且無響應,因此開發人員有時會使用該特性測試來分叉事件:
<div nonsense="true"> ... </div>
但是,此條件源於一個錯誤的假設——因為設備支持觸摸,因此將使用觸摸。但是觸摸屏筆記本電腦呢?用戶可能正在觸摸屏幕,也可能正在使用鼠標或觸控板;上面的代碼無法處理這種情況,因此用鼠標單擊將不會執行任何操作。
在這種情況下,解決方案根本不是測試事件支持——而是同時綁定兩個事件,然後使用 preventDefault
來阻止觸摸生成點擊:
if (navigator.userAgent.indexOf('MSIE 5') != -1) { // 我们认为此浏览器是 IE5 }
完全不起作用的東西
承認這一點很痛苦,但有時我們不需要測試的不是特性——而是瀏覽器——因為特定瀏覽器聲稱支持某些不起作用的東西。最近的一個例子是 Opera 12 中的 setDragImage()
(這是拖放 dataTransfer
對象的一種方法)。
特性測試在這裡失敗是因為 Opera 12 聲稱支持它;異常處理也無濟於事,因為它不會引發任何錯誤。它只是不起作用:
<code>Mozilla/5.0 (Macintosh; Intel Mac OS X 10_6_8) AppleWebKit/534.59.10 (KHTML, like Gecko) Version/5.1.9 Safari/534.59.10</code>
現在,如果您只想嘗試添加自定義拖動圖像,並且樂於在不支持的情況下保留默認值(這將發生),那麼這可能很好。但是,如果您的應用程序確實需要自定義圖像,以至於不支持它的瀏覽器應該使用完全不同的實現(即使用自定義 JavaScript 來實現所有拖動行為)呢?
或者,如果瀏覽器實現了某些功能,但存在無法避免的渲染錯誤呢?有時我們別無選擇,只能明確檢測有問題的瀏覽器,並將其排除在使用它本來會嘗試支持的功能之外。
因此,問題變成了——實現瀏覽器檢測最安全的方法是什麼?
我有兩點建議:
- 優先使用專有對象測試而不是 navigator 信息。
- 將其用於排除瀏覽器而不是包含瀏覽器。
例如,可以使用 window.opera
對象檢測 Opera 12 或更早版本,因此我們可以使用該排除來測試可拖動支持:
if (typeof document.documentElement.getBoundingClientRect != "undefined") { // 浏览器支持此函数 }
最好使用專有對象而不是標準對象,因為當發布新瀏覽器時,測試結果不太可能發生變化。以下是一些我最喜歡的示例:
if (typeof window.ActiveXObject != "undefined") { var request = new ActiveXObject("Microsoft.XMLHTTP"); }
對象測試也可以與特性測試結合使用,以確定特定瀏覽器中特定特性的支持,或者在緊急情況下,定義更精確的瀏覽器條件:
if (typeof window.ActiveXObject != "undefined") { try { var request = new ActiveXObject("Microsoft.XMLHTTP"); } catch (ex) { request = null; } if (request !== null) { //... 我们有一个请求对象 } }
我們已經註意到用戶代理字符串是一個不可靠的混亂,但供應商字符串實際上相當可預測,並且可以用來可靠地測試 Chrome 或 Safari:
if ("draggable" in element) { // 浏览器支持拖放 }
所有這一切的黃金法則是要極其小心。確保您在盡可能多的瀏覽器中測試條件,並仔細考慮它們的向前兼容性——目標是使用瀏覽器條件來排除瀏覽器,因為存在已知的錯誤,而不是因為已知的特性而包含它們(這就是特性測試的目的)
從根本上說,始終首先假設完全符合特性測試——除非您知道情況並非如此,否則假設特性將按預期工作。
選擇測試語法
在結束之前,我想檢查一下我們可以用於對象和特性測試的不同類型的語法。例如,近年來,以下語法已變得很常見:
if (navigator.userAgent.indexOf('MSIE 5') != -1) { // 我们认为此浏览器是 IE5 }
過去我們無法使用它,因為 IE5 及其同類產品會因語法而引發錯誤;但現在我們不必支持這些瀏覽器,這已不再是問題。
從本質上講,它與以下內容完全相同,但編寫起來更短:
<code>Mozilla/5.0 (Macintosh; Intel Mac OS X 10_6_8) AppleWebKit/534.59.10 (KHTML, like Gecko) Version/5.1.9 Safari/534.59.10</code>
但是,測試條件通常依賴於自動類型轉換:
if (typeof document.documentElement.getBoundingClientRect != "undefined") { // 浏览器支持此函数 }
我們在某些瀏覽器對象測試(例如window.opera
測試)中早些時候使用了該語法,這是安全的,因為對像如何評估——任何已定義的對像或函數都將始終評估為true,而如果它未定義,則將評估為false。
但是我們可能正在測試有效返回 null 或空字符串的東西,這兩者都評估為 false。例如,style.maxWidth
屬性有時用於排除 IE6:
if (typeof window.ActiveXObject != "undefined") { var request = new ActiveXObject("Microsoft.XMLHTTP"); }
只有在支持 maxWidth
屬性並且具有作者定義的值時,它才會評估為 true,因此如果我們這樣編寫測試,它可能會失敗:
if (typeof window.ActiveXObject != "undefined") { try { var request = new ActiveXObject("Microsoft.XMLHTTP"); } catch (ex) { request = null; } if (request !== null) { //... 我们有一个请求对象 } }
一般規則是這樣的:依賴於自動類型轉換對於對象和函數是安全的,但對於字符串和數字或可能為 null 的值並不一定安全。
話雖如此——如果您能安全地使用它,那就這樣做,因為它在現代瀏覽器中通常要快得多(可能是因為它們針對這種類型的條件進行了優化)。
有關此內容的更多信息,請參閱:現實世界中的自動類型轉換。
關於 JavaScript 特性檢測的常見問題
什麼是 JavaScript 特性檢測,為什麼它很重要?
JavaScript 特性檢測是開發人員用來確定用戶瀏覽器是否支持特定特性或 API 的一種技術。這至關重要,因為並非所有瀏覽器都支持 JavaScript 的所有特性。通過使用特性檢測,開發人員可以為不受支持的特性提供替代解決方案或後備方案,確保網站或應用程序在不同瀏覽器上都能正確運行。這增強了用戶體驗並確保了兼容性。
JavaScript 特性檢測是如何失敗的?
JavaScript 特性檢測可能會由於多種原因而失敗。一個常見的原因是特性檢測代碼的實現不正確。例如,如果代碼檢查對像中不存在的屬性,它將返回 undefined,導致假陰性。另一個原因可能是瀏覽器的怪癖或錯誤,這可能會導致特性檢測給出不准確的結果。
特性檢測和瀏覽器檢測有什麼區別?
特性檢測涉及檢查用戶瀏覽器是否支持特定特性或 API,而瀏覽器檢測則識別用戶的瀏覽器和版本。雖然這兩種技術都旨在確保兼容性和功能性,但特性檢測通常被認為是一種更好的實踐,因為它直接檢查特性,而不是根據瀏覽器類型或版本來假設其支持。
如何使用 JavaScript 檢測移動設備?
您可以使用 JavaScript 中的 navigator.userAgent
屬性來檢測移動設備。此屬性返回一個字符串,表示瀏覽器的用戶代理標頭。通過檢查此字符串中的特定關鍵字(例如“Android”、“iPhone”或“iPad”),您可以確定用戶是否在移動設備上。
什麼是 Feature.js,它如何幫助進行特性檢測?
Feature.js 是一個輕量級、快速且簡單的 JavaScript 實用程序,用於特性檢測。它提供易於使用的 API,允許開發人員測試瀏覽器是否支持特定特性。這有助於為不受支持的特性提供後備方案或替代解決方案,從而增強網站或應用程序的兼容性和功能性。
什麼是 Modernizr,它如何幫助進行特性檢測?
Modernizr 是一個 JavaScript 庫,可幫助開發人員利用 HTML5 和 CSS3 特性,同時保持與舊版瀏覽器的兼容性。它使用特性檢測來檢查瀏覽器是否支持特定特性,並將類添加到 HTML 元素,允許您在樣式表或 JavaScript 中定位特定瀏覽器功能。
如何使用 device-detector-js 包進行特性檢測?
device-detector-js 包是用於設備檢測的強大工具。它解析用戶代理字符串並檢測智能手機、平板電腦、台式機、電視機等設備。它還檢測瀏覽器、引擎、操作系統和其他有用信息。您可以使用此包根據檢測到的設備調整網站或應用程序的行為。
實施特性檢測的一些最佳實踐是什麼?
實施特性檢測的一些最佳實踐包括:使用可靠且經過測試的庫(如Modernizr 或Feature.js)、在不同的瀏覽器和設備上徹底測試您的特性檢測代碼、為不受支持的特性提供替代解決方案或後備方案以及避免根據瀏覽器類型或版本來假設特性支持。
特性檢測能否幫助提高網站性能?
是的,特性檢測可以幫助提高網站性能。通過檢測不受支持的特性並提供替代解決方案或後備方案,您可以防止不必要的代碼在瀏覽器中運行。這可以減少加載時間並提高網站的整體性能。
如何了解不同瀏覽器支持的最新特性?
由於 Web 開發的快速發展,了解不同瀏覽器支持的最新特性可能具有挑戰性。但是,Mozilla 開發者網絡 (MDN)、Can I Use 和 JavaScript 文檔等資源可以提供有關不同瀏覽器中特性支持的最新信息。
以上是當JavaScript功能檢測失敗時的詳細內容。更多資訊請關注PHP中文網其他相關文章!

選擇Python還是JavaScript應基於職業發展、學習曲線和生態系統:1)職業發展:Python適合數據科學和後端開發,JavaScript適合前端和全棧開發。 2)學習曲線:Python語法簡潔,適合初學者;JavaScript語法靈活。 3)生態系統:Python有豐富的科學計算庫,JavaScript有強大的前端框架。

JavaScript框架的強大之處在於簡化開發、提升用戶體驗和應用性能。選擇框架時應考慮:1.項目規模和復雜度,2.團隊經驗,3.生態系統和社區支持。

引言我知道你可能會覺得奇怪,JavaScript、C 和瀏覽器之間到底有什麼關係?它們之間看似毫無關聯,但實際上,它們在現代網絡開發中扮演著非常重要的角色。今天我們就來深入探討一下這三者之間的緊密聯繫。通過這篇文章,你將了解到JavaScript如何在瀏覽器中運行,C 在瀏覽器引擎中的作用,以及它們如何共同推動網頁的渲染和交互。 JavaScript與瀏覽器的關係我們都知道,JavaScript是前端開發的核心語言,它直接在瀏覽器中運行,讓網頁變得生動有趣。你是否曾經想過,為什麼JavaScr

Node.js擅長於高效I/O,這在很大程度上要歸功於流。 流媒體匯總處理數據,避免內存過載 - 大型文件,網絡任務和實時應用程序的理想。將流與打字稿的類型安全結合起來創建POWE

Python和JavaScript在性能和效率方面的差異主要體現在:1)Python作為解釋型語言,運行速度較慢,但開發效率高,適合快速原型開發;2)JavaScript在瀏覽器中受限於單線程,但在Node.js中可利用多線程和異步I/O提升性能,兩者在實際項目中各有優勢。

JavaScript起源於1995年,由布蘭登·艾克創造,實現語言為C語言。 1.C語言為JavaScript提供了高性能和系統級編程能力。 2.JavaScript的內存管理和性能優化依賴於C語言。 3.C語言的跨平台特性幫助JavaScript在不同操作系統上高效運行。

JavaScript在瀏覽器和Node.js環境中運行,依賴JavaScript引擎解析和執行代碼。 1)解析階段生成抽象語法樹(AST);2)編譯階段將AST轉換為字節碼或機器碼;3)執行階段執行編譯後的代碼。

Python和JavaScript的未來趨勢包括:1.Python將鞏固在科學計算和AI領域的地位,2.JavaScript將推動Web技術發展,3.跨平台開發將成為熱門,4.性能優化將是重點。兩者都將繼續在各自領域擴展應用場景,並在性能上有更多突破。


熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

WebStorm Mac版
好用的JavaScript開發工具

SecLists
SecLists是最終安全測試人員的伙伴。它是一個包含各種類型清單的集合,這些清單在安全評估過程中經常使用,而且都在一個地方。 SecLists透過方便地提供安全測試人員可能需要的所有列表,幫助提高安全測試的效率和生產力。清單類型包括使用者名稱、密碼、URL、模糊測試有效載荷、敏感資料模式、Web shell等等。測試人員只需將此儲存庫拉到新的測試機上,他就可以存取所需的每種類型的清單。

DVWA
Damn Vulnerable Web App (DVWA) 是一個PHP/MySQL的Web應用程序,非常容易受到攻擊。它的主要目標是成為安全專業人員在合法環境中測試自己的技能和工具的輔助工具,幫助Web開發人員更好地理解保護網路應用程式的過程,並幫助教師/學生在課堂環境中教授/學習Web應用程式安全性。 DVWA的目標是透過簡單直接的介面練習一些最常見的Web漏洞,難度各不相同。請注意,該軟體中

EditPlus 中文破解版
體積小,語法高亮,不支援程式碼提示功能

MinGW - Minimalist GNU for Windows
這個專案正在遷移到osdn.net/projects/mingw的過程中,你可以繼續在那裡關注我們。 MinGW:GNU編譯器集合(GCC)的本機Windows移植版本,可自由分發的導入函式庫和用於建置本機Windows應用程式的頭檔;包括對MSVC執行時間的擴展,以支援C99功能。 MinGW的所有軟體都可以在64位元Windows平台上運作。