Javascript检查yield支持

28

我读到了 JavaScript 中的 yield 关键字,需要在我的项目中使用它。我读到这个关键字是从某个版本的 JS 开始实现的,因此我认为旧版浏览器不支持它(是吗?)。

有没有办法检查是否支持 yield 关键字?或者至少有没有办法检查 JS 的版本是否大于或等于实现该关键字的版本(1.7)?

7个回答

33

这是一个检查是否可以使用yield的函数。

var can_yield = (function(){ 
    try { 
        return eval("!!Function('yield true;')().next()"); 
    } 
    catch(e) { 
        return false; 
    } 
})();

1
啊哈哈,喜欢那个 JavaScript :)) 给你点赞! - Darko

14

yield 引入了一种新的 JavaScript 语法。除非在 script type 属性中指定了版本号,否则您将无法使用 yield

当您指定一个脚本版本时,只有支持该版本的浏览器才会执行代码块。因此,在以下代码中,只有 Firefox 而不是 IE、Opera 或 WebKit 会执行顶部的代码块:

<script type="text/javascript;version=1.7">
    function x() {
        yield 0;
    }
    var canyield= true;
</script>
<script type="text/javascript">
    if (!window.canyield) {
        // do some fallback for other browsers
    }
</script>

(*:请注意,type 属性中指定的类型和版本独占地确定了外部脚本的获取、执行和执行模式。遗憾的是,脚本的 Content-Type 将完全被忽略。)


3
遗憾的是,这无法检测Chrome是否启用了实验性JavaScript标志,该标志从31.x版本开始在该浏览器中启用了yield。但在Firefox中表现很好。 - John McDonald

9
这是我的看法,关于检查本地 yield 支持。
var canYield = (function(){try{yield;}catch(e){}}())!==undefined;

Modernizr测试

define(['Modernizr'], function( Modernizr ) {
  // native yield support.
  Modernizr.addTest('yield', (function(){try{yield;}catch(e){}}())!==undefined);
});

Performance http://jsperf.com/yield-support enter image description here enter image description here


6
严格来说,只有Mozilla浏览器支持JavaScript。所有浏览器应该支持ECMAScript,早期版本的JavaScript是ECMAScript的实现。 这个网站列出了哪些版本的JavaScript在哪些浏览器上受支持。
MSIE使用JScript。JScript中没有yield。因此,在页面中使用yield会限制浏览器的支持。
请访问https://developer.mozilla.org/en/New_in_JavaScript_1.7获取关于使用JavaScript 1.7的信息。

1
那么没有其他方法可以检查它,除了使用浏览器嗅探吗? - mck89
这个答案已经过时了,因为Google Chrome现在已经支持yield - hippietrail

4
最近我花了很多时间研究yield,bobince并不完全正确,但即使在开启实验性JavaScript标志的情况下(chrome://flags/#enable-javascript-harmony),Chrome 31也不会将JavaScript版本解释为1.7块。由于Chrome 31和Firefox之间的实现差异,Tymon Sturgeon的方法无法在开启实验性JS的Chrome 31中检测到yield,尽管它非常接近。通过几个修改,可以检测到Firefox和Chrome 31在开启实验性JS时是否存在yield
首先,我将简要介绍yield的区别(为了清晰起见,我将其写成长篇小说):
在Firefox中:
var fooGen = function(){ yield 1; yield 2; };
var iterator = fooGen();
console.log(iterator.next());    // prints 1
console.log(iterator.next());    // prints 2

在启用试验性JavaScript的Chrome 31中:
// Note the *
var fooGen = function*(){ yield 1; yield 2; };
var iterator = fooGen();
console.log(iterator.next().value);    // prints 1
console.log(iterator.next().value);    // prints 2

.value在Chrome中是必需的,因为它会产生一个对象,但更重要的是,生成器函数定义中需要使用“*”符号。此外,在Chrome中无法从大写字母“F”的Function中创建生成器:new Function('', '{yield 5;}');。如果您知道如何做,请在下面留言。

为了正确检测Firefox和Chrome中的yield,我使用了一些代码进行了反复测试:

<script type="application/javascript">
    var can_yield = (function(){ 
        try {
            // Assuming Chrome's generator syntax
            var funcUsingYield = new Function('', '{ var interp = function* generator(){ yield true; }}');
            return true;
        } catch(e) { 
            return false; 
        } 
    })();
</script>

<script type="application/javascript;version=1.7">
    // Redefine the `can_yield` function inside a JS1.7 block. Probably safe to simply return true
    can_yield = (function(){ 
        try { 
            return eval("!!Function('yield true;')().next()"); 
        } 
        catch(e) { 
            return false; 
        } 
    })();
</script>

<script type="application/javascript">
    if(!can_yield)
    {
        alert("Can't Yield!");
    }
</script>

测试过的浏览器版本:

  • Firefox 25:支持yield
  • Chrome 31(开启实验性JS):支持yield
  • Chrome 31(关闭实验性JS):不支持yield
  • IE10:不支持yield

2
我们实际上在"纯JavaScript"中程序化地实现了"yield",即在没有使用Firefox "yield"的情况下,为Pyjamas完成了这项工作,注意到Skulpt也做了同样的事情。
理论上,完全可以通过手动方式(即通过遵循将函数转换为生成器的规则来费力地手动编写翻译函数)或通过运行JavaScript到JavaScript语言翻译器来完成完全相同的事情!
要实现这样一个"怪物"所需的是使函数能够跳过到它最后一次"退出"(通过yield语句)的点。因此,所有变量必须存储在临时状态中,并相应地改变代码执行方式,以接受这个临时状态信息。这包括while循环、for循环以及"if"语句。
它是可以做到的......
但这只是一项艰巨的工作:你需要有效地编写一个解析任何JavaScript程序的编译器,然后进行"转换",并输出修改后的JavaScript。
L.

这就是C#的实现方式 - Sebastian

1

实际上,有一些技巧可以使用,但我怀疑这些技巧是否具有真正的价值。

(function test_key_word(keyword){
var wrong = false;
try {
    eval(keyword + "=42");
} 
catch(e) {
    wrong = true;
} finally {
    if (wrong) { return "definitely wrong" }
    else 
    if (window[keyword] !== 42) {
        return "very probably, wrong"
    }
    else {
        return "can be acceptable, but nevertheless i wouldn't rely upon such tests"
    }
}})("in")

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接