How to get `let` statement work on major three browsers? - javascript

Firefox requires using <script type="application/javascript;version=1.7"> to activate ES6 let statement support.
Note: The let keyword is only available to code blocks in HTML wrapped in a <script type="application/javascript;version=1.7"> block (or higher version). XUL script tags have access to these features without needing this special block.
However, it seems that this actually deactivates the whole script on both Internet Explorer and Chrome, as their debuggers do not show the script anymore.
Example: http://embed.plnkr.co/7YvyDZfPRsijqrHJnhMf/preview
Is there any way to use application/javascript;version=1.7 on IE/Chrome, or to use ES6 let on Firefox without the type attribute?
Is there any hack to activate let statement support for all major browsers, while their implementations are not 100% standard-compliant?

You are asking the wrong question. You should not ask when <script type="application/javascript;version=1.7"> becomes available in other browsers, but when Firefox (and other browsers) will ship the let keyword as defined by the ECMAScript 6 standard. "JS 1.7" is a non-standard Firefox-only thing, and let in Firefox is slightly different from ES6's let keyword.
To know when let (and const, and block scope) is ready, just follow the following issues:
Firefox: https://bugzilla.mozilla.org/show_bug.cgi?id=950547
Chrome 41+ (Opera 28?): https://code.google.com/p/v8/issues/detail?id=2198
Internet Explorer 11+: https://status.modern.ie/blockbindingsletconstfunction (MSDN)

While we await the standard support of Firefox to the ES6 let keyword, you might want to dynamically load the script based on the type of browser you have using your server-side code (if you happen to be implementing a server-side web framework)
You might want to check the user agent string in order to detect the browser:
http://msdn.microsoft.com/en-us/library/ms537503(v=vs.85).aspx

Related

Safari browser reports error using classes in javascript

I use a class in my javascript.
class FileSet {
constructor(id,
path,
folder,
children,
all,
isfolder
) {
}
}
It works in all browsers except Safari.
In Safari I get the following exception.
SyntaxError: Use of reserved word 'class'
How do I make my script run in Safari browser.
Thanks,
Gagan
You might be using safari browser less that version 9. The class keyword is a reserved keywork in ES6 and safari browser do not support ES6 less than version 9. So, you must need to update your browser to version 9 or more to get your JavaScript work.

Javascript strict mode and versions

I want to use let in my code. Like so:
"use strict";
var b = 5;
for(let i =0;b > i; i++){
alert(i);
}
This is working in Chrome and IE. But not in Firefox.
Wrapping my code in script tags with the type attribute set to "application/javascript;version=1.7" like so:
<script type="application/javascript;version=1.7">
This fixes the problem in Firefox, but breaks the code in Chrome and IE.
The error Firefox gives me when i execute the first code snippet:
SyntaxError: let is a reserved identifier
Is there any way to support all browsers?
Avoid using let unless you're using a transcoder/transpiler to convert your js to code that is currently widely supported.
Let became standard in ECMA-262 but it'll be several years before a large enough portion of visitors support it natively to use it.
The following have basic support for let, everything below will break:
Chrome 41+
Gecko 2.0
IE11
Opera 17+
Safari ??
The above browsers likely have inconsistent implementations at this point, so it's best to avoid it.
Check out babel to transform.
Let as defined in ES2015 (ES6) is not yet supported in Firefox. It has an old version of let that is non standard and works slightly differently.
The current way to support it in all browsers is to use a transpiler like BabelJS.

how to ensure the browser can support **{get X() {}}**

i refuse to use __defineProperty__ and instead prefer the alternative syntax {get X() {}}
However this will not work on IE.
Aside from browser detection, what is the best way i can detect that a browser supports the newer syntax?
Edit: ok actually im not trying to detect IE in particular but redirect those "browsers that do not support get X(){} syntax" to notsupported.html. I believe that there's some way to do it and am working on it but in case someone already has this problem before and had a solution..
Edit 2: btw doesn't that mean that no one (erm other than me) uses the get X(){} syntax since its not supported by all (or not supported by the 5 major browsers yet) ?
As others have noted, you cannot force older (current!) browsers to accept newer syntax. And what would you do with browser detection? Use the old syntax for the old browsers and new syntax otherwise? Then you're writing the same code twice.
Decide on a set of browsers you need to support, determine what features they can all guarantee to you, then limit yourself to those features. That's how web development works.
You want to use an ES5 feature that is not commonly implemented.
You want to use syntax that common javascript interpreters cannot recognise.
There is no way to emulate it.
I recommend you just use
{
getX: function() { ... }
}
If you check the benchmark. Then you'll see using ES5 is 15 times slower. Just stick with ES3.
There is little you can do about this as there is no way to emulate getters in IE8.
Try this:
function browserSupportsGetterAndSetterSyntax() {
try {
return eval('({ get x() { return 3; }}).x') == 3;
} catch (e) {
return false;
}
}

Alternative methods for creating dynamic JavaScript?

Background
I am working on a project that runs in an embedded web browser in a small device with limited resources. The browser itself is a bit dated and has limits to its capabilities (HTML 4.01†, W3C DOM Level 2†, JavaScript 1.4). I have no documentation on the browser, so what I do know comes from trial and error.
The point is to retrieve dynamic content from a server so that only a minimal amount of inflexible code needs to be embedded into the device running the web browser. The browser does not support the XMLHTTPRequest object, so AJAX is out. Working with I do have, I wrote a bit of test code to dynamically insert JavaScript.
† Minor portions of these standards not supported
EDIT
While I cannot actually confirm it, I believe that this site may list the DOM support for the embedded browser because I see "Mozilla/4.0 (compatible; EBSWebC 2.6; Windows NT 5.1)" as the user agent in the server log.
<html>
<head>
</head>
<body onload="init()">
<div id="root"></div>
<script type="text/javascript">
<!--
function init() {
// Add a div element to the page.
var div = document.createElement("div");
div.id = "testDiv";
document.getElementById("root").appendChild(div);
// Set a timeout to insert the JavaScript after 2 seconds.
setTimeout("dynamicJS()", 2000);
}
function dynamicJS() {
...
}
//-->
</script>
</body>
</html>
Method 1
I initially implemented the dynamicJS function using Method 1 and found that while the code executes as expected in Chrome, IE8, and FireFox 3.5, the JavaScript is not actually retrieved by the embedded browser when the element is appended.
function dynamicJS() {
var js = document.createElement("script");
js.type = "text/javascript";
js.src = "js/test.js";
document.getElementById("root").appendChild(js);
}
Method 2
Looking for a work around, I implemented Method 2. This method actually works in the embedded browser as the JavaScript is retrieved and executed, but it does not work in other modern web browsers's I tested against (Chrome, IE8, FireFox 3.5).
function dynamicJS() {
var js= '<script type="text/javascript" src="js/test.js"> </s' + 'cript>';
document.getElementById("testDiv").innerHTML = js;
}
Question
I'm new to JavaScript and web programming in general, so I'm hoping one (or more) of the experts here can shed some light on this for me.
Is there anything technically wrong with Method 2 and if not, why doesn't it work in modern web browsers?
There is nothing technically wrong with method 2 but most modern browsers have very loose HTML parsers that tend to get caught up in the code that you're sending. Specifically they parse the </script> in your JavaScript string literal as an end tag. This manifests itself in two ways:
You'll see an "Unterminated String Literal" error.
All code after the </script> text will be rendered as text on the page.
A common workaround for this problem is to split the </script>. You can do this with the following code. Yes, I know its a hack, but it works around the problem.
function dynamicJS() {
var js= '<script type="text/javascript" src="js/test.js"></s' + 'cript>';
document.getElementById("testDiv").innerHTML = js;
}
Realistically though, you should be able to use your first approach strictly using the DOM APIs. I've found that some browsers can be really picky about loading scripts added by script in that they will only load them if they are placed as a child of the <head> element. This is how the YUILoader works, so I'd be surprised if it didn't work in all browsers.
Here's an example, you'll want to check this to make sure that it works in all browsers, and add some error checking around the assumption that there will be a <head> element but it give you the general idea.
if (!document.getElementsByTagName) {
document.getElementsByTagName = function(name) {
var nodes = [];
var queue = [document.documentElement];
while (queue.length > 0) {
var node = queue.shift();
if (node.tagName && node.tagName.toLowerCase() === name) {
nodes.push(node);
}
if (node.childNodes && node.childNodes.length > 0) {
for (var i=0; i<node.childNodes.length; i++) {
if (node.childNodes[i].nodeType === 1 /* element */) {
queue.push(node.childNodes[i]);
}
}
}
}
return nodes;
};
}
function dynamicJS() {
var js = document.createElement("script");
js.setAttribute('type', 'text/javascript');
js.setAttribute('src', 'js/test.js');
var head = document.getElementsByTagName('head')[0];
head.appendChild(js);
}
The innerHTML property has not yet actually been standardized, though all modern browsers support it, and the draft standard of HTML5 includes a definition of how it should work. According to the HTML5 specification:
When inserted using the document.write() method, script elements execute (typically synchronously), but when inserted using innerHTML and outerHTML attributes, they do not execute at all.
innerHTML was first introduced in Microsoft Internet Explorer 4, and due to its popularity among authors, has been adopted by all of the other browsers, which is what led to its inclusion in HTML5. So, let's check Microsoft's documentation:
When using innerHTML to insert script, you must include the DEFER attribute in the script element.
So apparently, in IE you can get scripts inserted via innerHTML to execute, but only if you add a defer attribute (I do not have IE in front of me to test this). defer is another feature that was first added to IE; it was included in HTML 4.01, but not picked up by any of the other browsers for quite a while. HTML5 includes a much more detailed description of how <script defer> should work, though it appears to be slightly incompatible with how it works in IE, as it does not allow execution of scripts added via innerHTML. The HTML5 definition of <script defer> appears to be implemented in Firefox 3.5 and Safari 4.
In summary, innerHTML hasn't really been standardized yet, but instead simply implemented by all of the browser vendors in slightly different ways. In IE, the original implementation, it didn't support execution of scripts except with a defer attribute, and defer hasn't been supported in other browsers until just recently, and so the other browsers simply don't support execution of scripts added using innerHTML. This behavior is what HTML5 is standardizing on, so unless Microsoft objects, is probably going to be what goes into the standard.
It sounds like the browser you are working with didn't do as good a job of implementing a compatible innerHTML, as it executes scripts added using innerHTML no matter what. This is unsurprising, as the behavior isn't standardized and so needs to be either reverse engineered or gleaned from reading the documentation of other browsers (which may not have included this fact in the past). One of the main goals of HTML5 is to actually write down all of these unwritten assumptions and undocumented behaviors, so that in the future, someone implementing a browser can do so without being misled by a spec that doesn't match reality, or without having to do the effort of reverse engineering the existing browsers.
It looks to me that you may have to use Method 2 on your embedded browser, and Method 1 if you want to run on the common desktop browsers. It would probably be a good idea to try Method 1 first, and fall back to Method 2 if that does not work, and then error out (or silently fail, depending on your needs) if neither one works.
A long shot but does the embedded browser support iframes?
And if so would you be able to use that to load in whatever additional JS you needed and access it via the iframe?

Is there is reliable way to find out which revision of ECMA-262 my browser supports?

How do I find out if my browser supports Javascript 1.5 or not? using javascript of course. (or should I have googled or binged some more?)
For official “JavaScript”, that is Mozilla's implementation of ECMA-262, you can use the type attribute to detect version:
<script type="text/javascript;version=1.5"> v= '1.5'; </script>
<script type="text/javascript;version=1.6"> v= '1.6'; </script>
<script type="text/javascript;version=1.7"> v= '1.7'; </script>
...
This also works in Opera, (recent versions of which claim to support JavaScript 1.5). IE and Webkit will not execute any script with a version parameter in its type.
This is similar to the old-school language attribute:
<script language="javascript1.5"> v= '1.5'; </script>
...
This is generally considered obsolete, but it does work in more browsers. Recent Webkit browsers claim to support 1.7 and all IEs claim to support 1.3 only.
IE has its own versioning scheme for JScript, which you can sniff for through conditional comments:
<script type="text/javascript">
/*#cc_on #if (#_jscript_version>=5.5)
v= '5.5';
#end #*/
</script>
Other browsers you can't find out. As for ECMA-262 version, all modern browsers support the baseline of Third Edition (yeah, OK, there are small differences and outright bugs, especially in IE, but still). No browser supports large amounts of Fifth Edition yet, though that will come. (There was no Fourth Edition.)
None of this is very useful. As you can see, version numbers are all pretty woolly and don't really reflect what the browser supports terribly well. You are generally better off doing capability-sniffing. For example if you want ECMA-262-5's JSON features, see if window.JSON exists. If you want function binding, see if .bind exists on your function. You can often detect the lack of such features and patch in a native-JavaScript fallback for when they aren't available.
The syntactical features of JavaScript, however, can't be sniffed for. Just including something like a getter/setter definition in a block of JavaScript code will immediately give a syntax error in IE before you could sniff for their availability. But then this is usually not too big a problem because in practice you can't use these newer features anyway.
Its typically not worth trying.
If you want to make use of a specific feature, query to see if that feature is supported instead.
Even then, there's no guarantee that the feature is implemented correctly! ;-)
Case in point... IE supports document.getElementById(id); however unless you are using IE8 in IE8 Standards mode it can return one of many wrong results.
Another way you can do it, you can put inside try block some of it's syntax. for example:
try{
"use strict";
let x=1;//if it's works, then you have some supprot
console.info("Good news, ecma6 works ");
}catch(e){
console.warn("Sorry, but ecma6 still doesn't supported");
}
You can specify which version of Javascript should evaluate a block of code like this:
<script language="javascript1.5">
//this code gets run
</script>
More info here.
There are scripts out there that will generate a float containing the Javascript version. Here's a nice read on detection with Javascript: https://developer.mozilla.org/En/Browser_Detection_and_Cross_Browser_Support
Here is such script: http://www.docsteve.com/DocSteve/Samples/JS/js_version.html

Categories