Javascript检查产量支持

时间:2010-02-19 15:11:32

标签: javascript keyword yield yield-keyword

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

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

7 个答案:

答案 0 :(得分:33)

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

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

答案 1 :(得分:14)

yield为JavaScript引入了新的语法。除非您通过在yield属性(*)中包含版本号来指定您需要新的JavaScript语法,否则将无法使用script type

指定脚本版本时,只有支持给定版本的浏览器才会执行该块。因此,只有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是,完全被忽略了。)

答案 2 :(得分: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);
});

<强>性能 http://jsperf.com/yield-support enter image description here enter image description here

答案 3 :(得分:6)

严格来说,只有Mozilla浏览器支持JavaScript。所有浏览器应该支持ECMAScript,旧版本的JavaScript是ECMAScript的实现。

This site列出了哪些版本的浏览器支持哪些版本的Javascript。

MSIE使用JScript。 JScript没有产量。因此,使用yield会限制浏览器对页面的支持。

请尝试https://developer.mozilla.org/en/New_in_JavaScript_1.7了解有关使用JavaScript 1.7的信息

答案 4 :(得分:4)

我最近在yield上花了很多时间,并且bobince并非完全错误,但Chrome 31并没有将JavaScript版本解释为1.7版块,即使启用了实验性JavaScript标记(chrome:/ /标记/#启用JavaScript的-和谐)。由于Chrome 31和Firefox之间的实施差异,Tymon Sturgeon的方法无法在Chrome 31中使用Experimental JS检测到yield,尽管它非常接近。通过一些修改,它可以通过实验JS检测Firefox和Chrome 31的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
Chrome中需要

.value,因为它会生成一个对象,但更重要的是,生成器在函数定义中需要“*”。另外,我找不到从Chrome中的大写“F”函数: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正常工作
  • 实验JS 关闭
  • Chrome 31 yield不起作用
  • IE10 yield不起作用

答案 5 :(得分:2)

我们实际上以编程的方式在“纯javascript”中实现了“yield”,即在没有使用FIREFOX“yield”的情况下,穿着睡衣,注意到skulpt也做了同样的事情。

理论上,完全相同的事情可以手动完成(即通过遵循关于如何将函数转换为生成器的规则,通过手工编码翻译函数)或通过javascript-to-javascript运行javascript语言翻译(!)

实现这样一个“野兽”所需要的是你必须使该函数能够跳过它最后“退出”的位置(通过一个yield语句)。因此,所有变量必须以临时状态(!)存储,并且相应地改变代码执行,以接受此临时状态信息。包括while语句,for循环以及“if”语句。

可以完成......

...但它只是一个工作的婊子:你需要,有效地编写一个解析任何javascript程序的整个编译器,然后“转换”它,然后输出修改后的javascript。

1

答案 6 :(得分: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")