Javascript check yield support
I read about the yield keyword in JavaScript and I need to use it in my project. I read that this keyword has been implemented start开发者_如何学Going from a certain version of JS so I think that old browsers don't support it (right?).
Is there a way to check if the yield keyword is supported? or at least is there a way to check if the version of JS is greater or equal than the one that implements that keyword (1.7)?
Here's a function for checking if yield can be used.
var can_yield = (function(){
try {
return eval("!!Function('yield true;')().next()");
}
catch(e) {
return false;
}
})();
yield
introduces new syntax to JavaScript. You won't be able to use yield
unless you have specified that you want the new JavaScript syntax, by including a version number in the script type
attribute(*).
When you specify a script version, only browsers that support the given version will execute the block at all. So only Firefox, and not IE, Opera or WebKit, will execute the top block in:
<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>
(*: note that the type and version specified in the type
attribute exclusively determines whether external scripts are fetched, executed, and the mode for the execution. The Content-Type
of a script is, unfortunately, completely ignored.)
Here's my take on checking for native yield
support.
var canYield = (function(){try{yield;}catch(e){}}())!==undefined;
Modernizr test
define(['Modernizr'], function( Modernizr ) {
// native yield support.
Modernizr.addTest('yield', (function(){try{yield;}catch(e){}}())!==undefined);
});
Performance http://jsperf.com/yield-support
Strictly speaking, only Mozilla Browsers support JavaScript. All browsers should support ECMAScript and older versions of JavaScript are implementations of ECMAScript.
This site lists what versions of Javascript are supported on what versions of browser.
MSIE uses JScript. JScript does not have yield in it. Therefore, using yield will limit the browser support for your page.
Try https://developer.mozilla.org/en/New_in_JavaScript_1.7 for info on using JavaScript 1.7
I have spent a lot of time with yield
recently, and bobince isn't completely wrong, but Chrome 31 does not interpret JavaScript version to 1.7 blocks, even with the Experimental JavaScript flag turned on (chrome://flags/#enable-javascript-harmony). Due to implementation differences between Chrome 31 and Firefox, Tymon Sturgeon's method is unable to detect yield
in Chrome 31 with Experimental JS on, although it is very close. With a few modifications, it can detect the existence of yield
for both Firefox and Chrome 31 with Experimental JS on.
First I'll quickly cover the yield
differences (writing it the long way for clarity):
In Firefox:
var fooGen = function(){ yield 1; yield 2; };
var iterator = fooGen();
console.log(iterator.next()); // prints 1
console.log(iterator.next()); // prints 2
In Chrome 31 with Experimental JavaScript enabled:
// 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
is required in Chrome because it yields an object, but more importantly, the generator requires a "*" in the function definition. Also, I could not find a way to create a generator from the capital "F" Function: new Function('', '{yield 5;}');
in Chrome. If you know how, leave a comment below.
To properly detect yield
in Firefox and Chrome, I have used a bit of code with some back and forth:
<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>
Tested in:
- Firefox 25:
yield
works - Chrome 31 with Experimental JS On:
yield
works - Chrome 31 with Experimental JS Off:
yield
does not work - and IE10:
yield
does not work
we actually implemented "yield", programmatically, in "pure javascript" i.e. WITHOUT USING FIREFOX "yield", for pyjamas, after noting that skulpt also had done likewise.
in theory, the exact same thing could be done either manually (i.e. by laboriously hand-coding a translated function by following the rules on how to turn a function into a generator) or by running javascript through a javascript-to-javascript language translator (!)
what's required to implement such a "Beast" is that you have to make the function capable of skipping up to the point where it was last "exited" (by a yield statement). thus, all variables must be stored in temporary state (!) and the code-execution altered accordingly, to accept this temporary state-info. that includes while statements, for loops as well as "if" statements.
it can be done...
... but it's just a bitch of a job: you need, effectively to write an entire compiler that parses any javascript program, then "transforms" it, and then outputs the modified javascript.
l.
whell, actually there are some techniques you can use, but I doubt such techniques have any real value
(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")
精彩评论