Javascript ES6跨浏览器检测
如何找到浏览器的Javascript引擎版本和对ECMAScript 6的支持 我使用Javascript ES6跨浏览器检测,javascript,ecmascript-6,Javascript,Ecmascript 6,如何找到浏览器的Javascript引擎版本和对ECMAScript 6的支持 我使用navigator.appVersion只是为了知道浏览器的版本,而不是引擎的版本 检测devicePixelRatio,这是中的一个特殊属性 检测javaEnabled函数的实现 (函数(){ var v8string='函数%20javaEnabled%28%29%20%7B%20%5B本机%20code%5D%20%7D'; var es6string='函数%20javaEnabled%28%29%2
navigator.appVersion
只是为了知道浏览器的版本,而不是引擎的版本
(函数(){
var v8string='函数%20javaEnabled%28%29%20%7B%20%5B本机%20code%5D%20%7D';
var es6string='函数%20javaEnabled%28%29%20%7B%0A%20%20%20%20%5b本机%20code%5D%0A%7D';
if(window.devicePixelRatio)//if WebKit浏览器
{
var s=escape(navigator.javaEnabled.toString());
如果(s==v8string){
警报(“检测到V099787”);
}else if(s==es6string){
警报(“检测到ES6”)
}否则{
警报(“检测到JSC”);
}
}否则{
显示(“非WebKit浏览器”);
}
功能显示(msg){
var p=document.createElement('p');
p、 innerHTML=msg;
文件.正文.附件(p);
}
})()
特征检测
我建议您使用功能检测,而不是使用启发式方法检测浏览器引擎。为此,您可以简单地在语句中包装一些代码,或者使用一些if(…)
语句
例如:
function check() {
if (typeof SpecialObject == "undefined") return false;
try { specialFunction(); }
catch (e) { return false; }
return true;
}
if (check()) {
// Use SpecialObject and specialFunction
} else {
// You cannot use them :(
}
为什么特征检测优于浏览器/引擎检测?
在大多数情况下,有多种原因使特征检测成为最佳选择:
- 您不必依赖于浏览器的版本、引擎或细节,也不必使用难以实现且相当狡猾的启发式方法来检测它们
- 您不会在浏览器/引擎规格检测方面出错
- 您不必担心特定于浏览器的特性:例如,浏览器的规格与其他浏览器不同
- 您可以确信,一旦检测到某个功能,您就能够使用它
这些都是IMHO使特征检测成为最佳方法的主要原因
特征检测+回退
当使用功能检测时,当您不确定哪些功能可以/不能使用时,一个非常聪明的工作方式是多个功能检测,并随后退回到更基本的方法(甚至从头开始创建这些方法),以防您想要使用的功能不受支持
具有回退功能的功能检测的一个简单示例可以应用于窗口.requestAnimationFrame
功能,这不是所有浏览器都支持的功能,它有几个不同的前缀,具体取决于您使用的浏览器。在这种情况下,您可以像这样轻松地检测和回退:
requestAnimationFrame =
window.requestAnimationFrame // Standard name
|| window.webkitRequestAnimationFrame // Fallback to webkit- (old versions of Chrome or Safari)
|| window.mozRequestAnimationFrame // Fallback to moz- (Mozilla Firefox)
|| false; // Feature not supported :(
// Same goes for cancelAnimationFrame
cancelAnimationFrame = window.cancelAnimationFrame || window.webkitCancelAnimationFrame || window.mozCancelAnimationFrame || false;
if (!requestAnimationFrame) {
// Not supported? Build it by yourself!
requestAnimationFrame = function(callback) {
return setTimeout(callback, 0);
}
// No requestAnim. means no cancelAnim. Built that too.
cancelAnimationFrame = function(id) {
clearTimeout(id);
}
}
// Now you can use requestAnimationFrame
// No matter which browser you're running
var animationID = requestAnimationFrame(myBeautifulFunction);
const script = document.createElement('script');
script.setAttribute('nomodule', '');
script.innerHTML = 'window.nomodules = true;';
document.head.insertBefore(script, document.head.firstChild);
script.remove();
ECMAScript 6(和声)特征检测
现在,来谈谈真正的问题:如果你想检测到对ES6的支持,你就不能像我上面所说的那样,因为ES6的一系列相关功能都是基于新的语法和私有词,如果在ES5中使用,就会抛出一个语法错误
,这意味着编写同时包含ES5和ES6的脚本是不可能的强>
这里有一个例子来说明这个问题;下面的代码段不起作用,在执行之前将被阻止,因为它包含非法语法
function check() {
"use strict";
try { eval("var foo = (x)=>x+1"); }
catch (e) { return false; }
return true;
}
if (check()) {
var bar = (arg) => { return arg; }
// THIS LINE will always throw a SyntaxError in ES5
// even before checking for ES6
// because it contains illegal syntax.
} else {
var bar = function(arg) { return arg; }
}
现在,由于不能在同一个脚本中有条件地检查和执行ES6,您必须编写两个不同的脚本:一个只使用ES5,另一个包含ES6功能。使用两个不同的脚本,只有在支持ES6的情况下,您才能导入ES6,并且不会导致抛出语法错误
ES6检测和条件执行示例
现在,让我们制作一个更相关的示例,假设您希望在ES6脚本中使用以下功能:
- 新的
符号
对象
- 使用
class
关键字构建的类
- Arrow(
(…)=>{…}
)函数
注意:新引入语法的功能检测(如箭头函数)只能使用eval()
函数或其他等效函数(如function()
)完成,因为写入无效语法将在脚本执行之前停止脚本。这也是为什么不能使用if
语句来检测类和箭头函数的原因:这些特性与关键字和语法有关,因此包装在try{…}catch(e){…}
块中的eval(…)
可以正常工作
那么,来看看真正的代码:
- HTML标记:
- 您的
es5script.js
脚本中的代码:
函数检查(){
“严格使用”;
if(typeof Symbol==“undefined”)返回false;
试一试{
评估(“类别Foo{}”);
评估(“var bar=(x)=>x+1”);
}catch(e){return false;}
返回true;
}
if(check()){
//引擎支持您想要使用的ES6功能
var s=document.createElement('script');
s、 src=“es6script.js”;
文件。标题。附录子项;
}否则{
//引擎不支持这些ES6功能
//使用ES5:(
}
es6script.js中的代码
:
// Just for example...
"use strict";
class Car { // yay!
constructor(speed) {
this.speed = speed;
}
}
var foo = Symbol('foo'); // wohoo!
var bar = new Car(320); // blaze it!
var baz = (name) => { alert('Hello ' + name + '!'); }; // so cool!
浏览器/引擎检测
正如我上面所说,在编写JavaScript脚本时,浏览器和引擎检测并不是最佳实践。我将向您介绍有关此主题的一些背景知识,只是不想把我的话作为“随机的个人意见”
引用MDN文档[]:
当考虑使用用户代理字符串来检测正在使用的浏览器时,第一步是尽可能避免使用它。首先,请尝试确定为什么要这样做
[…]<script>
// This script block should not compile on incompatible browsers,
// leaving the function name undefined.
// It can then be polyfilled with a function containing compatible syntax code.
function fame() {
/* incompatible syntax code such as arrow functions */
}
</script>
<script>
if (typeof fame !== "function") {
// alert("polyfill: fame");
function fame() {
/* compatible syntax code */
}
}
</script>
<script>
// main code
fame();
</script>
function isES6()
{
try
{
Function("() => {};"); return true;
}
catch(exception)
{
return false;
}
}
...
<head>
<script nomodule>window.nomodules = true;</script>
<script>console.log(window.nomodules)</script>
</head>
...
const script = document.createElement('script');
script.setAttribute('nomodule', '');
script.innerHTML = 'window.nomodules = true;';
document.head.insertBefore(script, document.head.firstChild);
script.remove();
// If ES6 arrow functions are supported then the worker listener will receive true, otherwise it will receive an error message
(() => {
postMessage(true);
})();
if (typeof (Worker) !== "undefined") {
var myWorker = new Worker('worker.js');
myWorker.onmessage = function (e) {
// arrow functions must be supported since we received message from the worker arrow function
}
myWorker.onerror = function (e) {
// the worker triggered an error so arrow function not supported (could explicitly check message for syntax error)
}
}
<script>
window.isES6 = false;
</script>
<script>
// Arrow functions support
() => { };
// Class support
class __ES6FeatureDetectionTest { };
// Object initializer property and method shorthands
let a = true;
let b = {
a,
c() { return true; },
d: [1,2,3],
};
// Object destructuring
let { c, d } = b;
// Spread operator
let e = [...d, 4];
window.isES6 = true;
</script>
<script>
document.body.innerHTML += 'isES6: ' + window.isES6;
</script>