检测Safari浏览器

时间:2011-10-30 10:42:37

标签: javascript browser-detection

如何使用JavaScript检测Safari浏览器?我在下面尝试了代码,它不仅可以检测Safari,还可以检测Chrome浏览器。

function IsSafari() {

  var is_safari = navigator.userAgent.toLowerCase().indexOf('safari/') > -1;
  return is_safari;

}

22 个答案:

答案 0 :(得分:105)

注意:始终尝试检测您尝试修复的具体行为,而不是使用isSafari?

进行定位

作为最后的手段,使用此正则表达式检测Safari:

var isSafari = /^((?!chrome|android).)*safari/i.test(navigator.userAgent);

它使用negative look-arounds,不包括Chrome,Edge以及在其用户代理中包含Safari名称的所有Android浏览器。

答案 1 :(得分:89)

您可以轻松使用Chrome的索引来过滤Chrome:

var ua = navigator.userAgent.toLowerCase(); 
if (ua.indexOf('safari') != -1) { 
  if (ua.indexOf('chrome') > -1) {
    alert("1") // Chrome
  } else {
    alert("2") // Safari
  }
}

答案 2 :(得分:66)

正如其他人已经指出的那样,功能检测比检查特定浏览器更受欢迎。一个原因是可以更改用户代理字符串。另一个原因是字符串可能会在较新版本中更改并破坏您的代码。

如果你仍然想要测试任何Safari版本,我建议使用这个

var isSafari = navigator.vendor && navigator.vendor.indexOf('Apple') > -1 &&
               navigator.userAgent &&
               navigator.userAgent.indexOf('CriOS') == -1 &&
               navigator.userAgent.indexOf('FxiOS') == -1;

这适用于所有设备上的任何版本的Safari:Mac,iPhone,iPod,iPad。

修改

要在当前浏览器中进行测试:https://jsfiddle.net/j5hgcbm2/

编辑2

根据Chrome docs更新,以便正确检测iOS上的Chrome

值得注意的是,iOS上的所有浏览器都只是Safari的包装器并使用相同的引擎。请参阅bfred.it在此主题中对自己答案的评论。

编辑3

根据Firefox docs更新,以正确检测iOS上的Firefox

答案 3 :(得分:30)

只需使用:

var isSafari = window.safari !== undefined;
if (isSafari) console.log("Safari, yeah!");

答案 4 :(得分:18)

此代码仅用于检测safari浏览器

if (navigator.userAgent.search("Safari") >= 0 && navigator.userAgent.search("Chrome") < 0) 
{
   alert("Browser is Safari");          
}

答案 5 :(得分:9)

因为用于chrome和safari的userAgent几乎相同,所以可以更容易地查看浏览器的供应商

<强> Safari浏览器

navigator.vendor ==  "Apple Computer, Inc."

<强>铬

navigator.vendor ==  "Google Inc."

FireFox (为什么它是空的?)

navigator.vendor ==  ""

IE (为什么未定义?)

navigator.vendor ==  undefined

答案 6 :(得分:5)

只有 Safari 才能使用Chrome:

尝试其他代码后,我发现没有任何适用于新旧版本的Safari。

最后,我做了一个对我来说非常好的代码:

var ua = navigator.userAgent.toLowerCase(); 
var isSafari = false;
try {
  isSafari = /constructor/i.test(window.HTMLElement) || (function (p) { return p.toString() === "[object SafariRemoteNotification]"; })(!window['safari'] || safari.pushNotification);
}
catch(err) {}
isSafari = (isSafari || ((ua.indexOf('safari') != -1)&& (!(ua.indexOf('chrome')!= -1) && (ua.indexOf('version/')!= -1))));

//test
if (isSafari)
{
  //Code for Safari Browser (Desktop and Mobile)
  document.getElementById('idbody').innerHTML = "This is Safari!";
}
else
{
  document.getElementById('idbody').innerHTML = "Not is Safari!";
}
<body id="idbody">
</body>

答案 7 :(得分:3)

我用这个

function getBrowserName() {
    var name = "Unknown";
    if(navigator.userAgent.indexOf("MSIE")!=-1){
        name = "MSIE";
    }
    else if(navigator.userAgent.indexOf("Firefox")!=-1){
        name = "Firefox";
    }
    else if(navigator.userAgent.indexOf("Opera")!=-1){
        name = "Opera";
    }
    else if(navigator.userAgent.indexOf("Chrome") != -1){
        name = "Chrome";
    }
    else if(navigator.userAgent.indexOf("Safari")!=-1){
        name = "Safari";
    }
    return name;   
}

if( getBrowserName() == "Safari" ){
    alert("You are using Safari");
}else{
    alert("You are surfing on " + getBrowserName(name));
}

答案 8 :(得分:2)

我发现只有一个词可以区分Safari - “版本”。所以这个正则表达式将是完美的:

/.*Version.*Safari.*/.test(navigator.userAgent)

答案 9 :(得分:2)

就我而言,我需要同时针对iOS和macOS上的Safari。这对我有用:

if (/apple/i.test(navigator.vendor)) {
  // It's Safari
}

答案 10 :(得分:2)

最简单的答案:

function isSafari() {
 if (navigator.vendor.match(/[Aa]+pple/g).length > 0 ) 
   return true; 
 return false;
}

答案 11 :(得分:2)

作记录,我发现最安全的方法是实施this answer中浏览器检测代码的Safari部分:

const isSafari = window['safari'] && safari.pushNotification &&
    safari.pushNotification.toString() === '[object SafariRemoteNotification]';

当然,处理浏览器特定问题的最佳方法始终是进行特征检测(如果可能的话)。但是,使用类似上面的代码仍然比代理字符串检测更好。

答案 12 :(得分:2)

我不知道为什么OP想要检测Safari,但是在极少数情况下,如今您需要浏览器嗅探,检测渲染引擎可能比浏览器名称更重要。例如,在iOS上,所有浏览器都使用Safari / Webkit引擎,因此,如果底层渲染器实际上是Safari / Webkit,则将“ chrome”或“ firefox”作为浏览器名称毫无意义。我尚未在旧的浏览器上测试过此代码,但它可用于Android,iOS,OS X,Windows和Linux上的所有最新版本。

<script>
    let browserName = "";

    if(navigator.vendor.match(/google/i)) {
        browserName = 'chrome/blink';
    }
    else if(navigator.vendor.match(/apple/i)) {
        browserName = 'safari/webkit';
    }
    else if(navigator.userAgent.match(/firefox\//i)) {
        browserName = 'firefox/gecko';
    }
    else if(navigator.userAgent.match(/edge\//i)) {
        browserName = 'edge/edgehtml';
    }
    else if(navigator.userAgent.match(/trident\//i)) {
        browserName = 'ie/trident';
    }
    else
    {
        browserName = navigator.userAgent + "\n" + navigator.vendor;
    }
    alert(browserName);
</script>

要澄清:

  • iOS下的所有浏览器都将报告为“ safari / webkit”
  • 除Firefox外,所有Android下的浏览器都将报告为“ chrome / blink”
  • 在Windows,OS X或Linux下,
  • Chrome,Opera,Blisk,Vivaldi等都将被报告为“ chrome / blink”。

答案 13 :(得分:2)

我知道这个问题已经过时了,但我还是想找到答案,因为它可能对某人有所帮助。上述解决方案在某些边缘情况下失败,因此我们必须以分别处理iOS,桌面和其他平台的方式实现它。

function isSafari() {
    var ua = window.navigator.userAgent;
    var iOS = !!ua.match(/iP(ad|od|hone)/i);
    var hasSafariInUa = !!ua.match(/Safari/i);
    var noOtherBrowsersInUa = !ua.match(/Chrome|CriOS|OPiOS|mercury|FxiOS|Firefox/i)
    var result = false;
    if(iOS) { //detecting Safari in IOS mobile browsers
        var webkit = !!ua.match(/WebKit/i);
        result = webkit && hasSafariInUa && noOtherBrowsersInUa
    } else if(window.safari !== undefined){ //detecting Safari in Desktop Browsers
        result = true;
    } else { // detecting Safari in other platforms
        result = hasSafariInUa && noOtherBrowsersInUa
    }
    return result;
}

答案 14 :(得分:1)

这个独特的问题&#34;是浏览器是Safari的100%标志(信不信由你)。

if (Object.getOwnPropertyDescriptor(Document.prototype, 'cookie').descriptor === false) {
   console.log('Hello Safari!');
}

这意味着在Safari上将cookie对象描述符设置为false,而在其他所有情况下都是如此,这实际上让我对另一个项目感到头疼。快乐的编码!

答案 15 :(得分:1)

修改了正则表达式以回答above

var isSafari = /^((?!chrome|android|crios|fxios).)*safari/i.test(navigator.userAgent);
  • crios - Chrome
  • fxios - Firefox

答案 16 :(得分:1)

阅读许多答案和文章,并确定最准确的解决方案。在Safari,Chrome,Firefox(台式机和iOS版本)中进行了测试。首先,我们需要检测Apple供应商,然后排除Chrome和Firefox(适用于iOS)。

let isSafari = navigator.vendor.match(/apple/i) &&
             !navigator.userAgent.match(/crios/i) &&
             !navigator.userAgent.match(/fxios/i);

if (isSafari) {
  //
} else {
  //
}

答案 17 :(得分:0)

也许这有效:

Object.prototype.toString.call(window.HTMLElement).indexOf('Constructor')

编辑:不再工作

答案 18 :(得分:0)

我测试了#Christopher Martin 发布的代码,它报告我的浏览器为 Chrome,因为它在测试 Edge 之前测试了它,否则它将对旨在识别 Chrome 的测试回答正确。我修改了他的答案以纠正该缺陷和另外两个缺陷,即:

  1. Edge 的缩写用户代理子字符串
  2. 非常古老的 MSIE 字符串

将代码转换为函数会产生以下通过调试控制台报告的函数和测试脚本。

    <script type="text/javascript">
    function BasicBrowserSniffer ( )
    {
        if ( navigator.userAgent.match ( /edge\//i ) ) {
            return 'edge/edgehtml';
        }
        if ( navigator.userAgent.match ( /edg\//i ) ) {
            return 'edge/edgehtml';
        }
        else if ( navigator.vendor.match ( /google/i ) ) {
            return 'chrome/blink';
        }
        else if ( navigator.vendor.match ( /apple/i ) ) {
            return 'safari/webkit';
        }
        else if ( navigator.userAgent.match ( /firefox\//i ) ) {
            return 'firefox/gecko';
        }
        else if ( navigator.userAgent.match ( /trident\//i ) ) {
            return 'ie/trident';
        }
        else if ( navigator.userAgent.match ( /msie\//i ) ) {
            return 'ie/trident';
        }
        else
        {
            return navigator.userAgent + "\n" + navigator.vendor;
        }
    };  // BasicBrowserSniffer function

    console.info ( 'Entering function anonymous DocumentReady function' );
    console.info ( 'User Agent String   = ' + navigator.userAgent.toLowerCase ( ));
    console.info ( 'User Agent Vendor   = ' + var uav = navigator.vendor.toLowerCase ( );
    console.info ( 'BasicBrowserSniffer = ' + BasicBrowserSniffer ( ) );
    console.info ( 'Leaving function anonymous DocumentReady function' );
</script>

答案 19 :(得分:0)

基于@SudarP 的回答。

到 2021 年第 3 季度,此解决方案将在 Firefox ("Accept-Encoding": "gzip, deflate" ) 和 Chrome (Uncaught TypeError: navigator.vendor.match(...) is null) 中失败;

所以这是一个固定的、更短的解决方案:

Uncaught TypeError: Cannot read properties of null (reading 'length')

答案 20 :(得分:-1)

我创建了一个返回布尔类型的函数:

export const isSafari = () => navigator.userAgent.toLowerCase().indexOf('safari') !== -1

答案 21 :(得分:-3)

用户代理嗅探确实是棘手且不可靠的。我们试图通过上面@qingu的答案来检测iOS上的Safari,它对于Safari,Chrome和Firefox确实表现良好。但是它错误地将Opera和Edge检测为Safari。

因此我们进行了功能检测,从今天开始,serviceWorker仅在Safari中受支持,而在iOS上的任何其他浏览器中均不受支持。如https://jakearchibald.github.io/isserviceworkerready/

中所述

支持不包括该平台上的iOS版本的第三方浏览器(请参阅Safari支持)。

所以我们做了类似的事情

if ('serviceWorker' in navigator) {
    return 'Safari';
}
else {
    return 'Other Browser';
}

注意:未在MacOS的Safari上进行测试。