【发布时间】:2011-01-18 19:56:06
【问题描述】:
我阅读了 JavaScript 中的 yield 关键字,我需要在我的项目中使用它。我读到这个关键字是从某个版本的 JS 开始实现的,所以我认为旧浏览器不支持它(对吗?)。
有没有办法检查是否支持 yield 关键字?或者至少有办法检查 JS 的版本是否大于或等于实现该关键字的版本(1.7)?
【问题讨论】:
标签: javascript keyword yield yield-keyword
我阅读了 JavaScript 中的 yield 关键字,我需要在我的项目中使用它。我读到这个关键字是从某个版本的 JS 开始实现的,所以我认为旧浏览器不支持它(对吗?)。
有没有办法检查是否支持 yield 关键字?或者至少有办法检查 JS 的版本是否大于或等于实现该关键字的版本(1.7)?
【问题讨论】:
标签: javascript keyword yield yield-keyword
这是一个检查是否可以使用yield的函数。
var can_yield = (function(){
try {
return eval("!!Function('yield true;')().next()");
}
catch(e) {
return false;
}
})();
【讨论】:
yield 为 JavaScript 引入了新语法。您将无法使用yield,除非您通过在script type 属性(*) 中包含版本号来指定您需要新的JavaScript 语法。
当您指定脚本版本时,只有支持给定版本的浏览器才会执行该块。所以只有 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 被完全忽略。 )
【讨论】:
yield。不过在 Firefox 中效果很好。
这是我对原生 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);
});
【讨论】:
严格来说,只有 Mozilla 浏览器支持 JavaScript。所有浏览器应该支持 ECMAScript,旧版本的 JavaScript 是 ECMAScript 的实现。
This site 列出了哪些版本的浏览器支持哪些版本的 Javascript。
MSIE 使用 JScript。 JScript 中没有 yield。因此,使用 yield 会限制浏览器对您页面的支持。
尝试https://developer.mozilla.org/en/New_in_JavaScript_1.7 获取有关使用 JavaScript 1.7 的信息
【讨论】:
yield 支持。
我最近在yield 上花了很多时间,bobince 并没有完全错误,但是 Chrome 31 不会将 JavaScript 版本解释为 1.7 块,即使打开了 Experimental JavaScript 标志 (chrome://flags /#enable-javascript-harmony)。由于 Chrome 31 和 Firefox 之间的实现差异,Tymon Sturgeon 的方法无法在启用 Experimental JS 的 Chrome 31 中检测到yield,尽管它非常接近。通过一些修改,它可以在 Firefox 和 Chrome 31 上检测到 yield 的存在,并开启 Experimental JS。
首先,我将快速介绍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 中是必需的,因为它生成一个对象,但更重要的是,生成器在函数定义中需要一个“*”。另外,我找不到从大写“F”函数创建生成器的方法:Chrome 中的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>
测试于:
yield 有效yield 有效yield 不起作用yield 不起作用【讨论】:
我们实际上在“纯 javascript”中以编程方式实现了“yield”,即在没有使用 Firefox“yield”的情况下,对于睡衣,我们注意到 skulpt 也做了同样的事情。
理论上,完全相同的事情可以手动完成(即通过遵循如何将函数转换为生成器的规则,费力地手工编写翻译后的函数)或通过 javascript-to-javascript 运行 javascript语言翻译器(!)
实现这样的“野兽”所需的是,您必须使函数能够跳到上次“退出”的位置(通过 yield 语句)。因此,所有变量都必须存储在临时状态(!)中,并相应地更改代码执行,以接受此临时状态信息。其中包括 while 语句、for 循环以及“if”语句。
它可以完成...
... 但这只是一项工作:您需要有效地编写一个完整的编译器来解析任何 javascript 程序,然后“转换”它,然后输出修改后的 javascript。
l.
【讨论】:
嗯,其实有一些技巧你可以使用,但我怀疑这些技巧有什么真正的价值
(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")
【讨论】: