I was trying this JavaScript piece of code:
class User(name) {
this.name = name;
}
var class = new User("Kimo");
The above was used as is in a JavaScript book, and I was simply playing with it.
firefox 6.0.2 (from the console) refused the 'class' keyword as a variable name (complained about a syntax error), while chrome 13.0.782.220m (from the developer tool) didn't complain at all.
It makes me think, which one is right? Since the notion of a class in JavaScript doesn't exist or it is different than other OOP languages. On the other hand, it might be wiser to prevent developers from using it.
I would like to know why this different approaches between firefox and chrome (I know they use different engines).
Thanks
First of all you can`t create a class in Javascript like this. Either create an object:
var User = {...};
or a constructor function:
function User() {...}
class is reserved word from about.com (some not listed in ECMA 262, but present in JScript) and MDC - reserved for future use. It is true that JavaScript has no classes for the moment. But the word is reserved in the sense that some day it can have such.
Mozilla is more strict about the rules than other browsers and gives a syntax error.
In addition :
JavaScript is not purely Object Oriented Programming language ( OOP ) it is Prototype-based Programming language.
On the other hand, it might be wiser to prevent developers from using it.
As JavaScript is interpreted by the browser, I don`t think the usage of reserved words can be prohibited. In the compiled code you have the compiler to disagree with you about such things, before the product is ready to use.
One other thing - you can write JavaScript code on editor with no capabilities to tell you, that your code has errors, or that you use reserved words for variables.
An error is correct behavior. Class is a restricted keyword in ECMAScript.
Firefox didnt implement Class support yet, if you check ecma6 browser support aka javascript(its a new realease that will have more feactures such as class :D), you will see that Class for mozilla isnt possible, lets hope soon will be available, ecma 6 is in beta stage, so it will be a while till all browsers support all the feactures
Related
I'm using Typescript and I recently changed the transpilation options to target ES6 instead of ES5.
I was using a certain syntax that had always worked fine under ES5, but after the target change, I started getting this error in the (Firefox) browser console:
Javascript ES6 TypeError: Class constructor Client cannot be invoked without 'new'
I changed the code to a suitable syntax for ES6, and this fixed the issue, but I don't understand how the browser would know to throw this error in the first place, because the exact same code worked before.
Does the javascript parser in browser scan other parts of the code base and see they they're using ES6, and then reject this line because it doesn't match the ES6 code elsewhere?
Javascript doesn't enter any particular "mode".
Likely what really happened is that you were declaring a class Client. That is ES6 syntax, and it comes with the special caveat that you must use new Client to instantiate it. Now, your compiler compiled this into a backwards-compatible function Client() .... Obviously, you can call a function without new. And that's what you were doing somewhere.
So, the compilation from class to function masked the error. But when leaving the class as class (because ES6 target mode does not need to dumb it down to a function), the browser was actually dealing with a class and raised that error.
When declaring qx.log.appender.Native or qx.log.appender.Console, my IDE (PyCharm) complains about the syntax:
// Enable logging in debug variant
if (qx.core.Environment.get("qx.debug"))
{
qx.log.appender.Native;
qx.log.appender.Console;
}
(as documented here)
The warning I get is
Expression statement is not assignment or call
Is this preprocessor magic or a feature of JavaScript syntax I'm not aware yet?
Clarification as my question is ambiguous:
I know that this is perfectly fine JavaScript syntax. From the comments I conclude that here's no magic JS behavior that causes the log appenders to be attached, but rather some preprocessor feature?!
But how does this work? Is it an hardcoded handling or is this syntax available for all classes which follow a specific convention?
The hints how to turn off linter warnings are useful, but I rather wanted to know how this "magic" works
Although what's there by default is legal code, I find it to be somewhat ugly since it's a "useless statement" (result is ignored), aside from the fact that my editor complains about it too. In my code I always change it to something like this:
var appender;
appender = qx.log.appender.Native;
appender = qx.log.appender.Console;
Derrell
The generator reads your code to determine what classes are required by your application, so that it can produce an optimised application with only the minimum classes.
Those two lines are valid Javascript syntax, and exist in order to create a reference to the two classes so that the generator knows to include them - without them, you wouldn't have any logging in your application.
Another way to create the references is to use the #use compiler hint in a class comment, eg:
/**
* #use(qx.log.appender.Native)
* #use(qx.log.appender.Console)
*/
qx.Class.define("mypackage.Application", {
extend: qx.application.Standalone,
members: {
main: function() {
this.base(arguments);
this.debug("Hello world");
}
}
});
This works just as well and there is no unusual syntax - however, in this version your app will always refer to the those log appenders, whereas in the skeleton you are using the references to qx.log.appender.Native/Console were surrounded by if (qx.core.Environment.get("qx.debug")) {...} which means that in the non-debug, ./generate.py build version of your app the log appenders would normally be excluded.
Whether you think this is a good thing or not is up to you - personally, these days I ship all applications with the log appenders enabled and working so that if someone has a problem I can look at the logs (you can write your own appender that sends the logs to the server, or just remote control the user's computer)
EDIT: One other detail is that when a class is created, it can have a defer function that does extra initialisation - in this case, the generator detects qx.log.appender.Console is needed so it makes sure the class is loaded; the class' defer method then adds itself as an appender to the Qooxdoo logging system
This is a valid JS syntax, so most likely it's linter's/preprocessor's warning (looks like something similar to ESLint's no-unused-expressions).
Edit:
For the other part of the question - this syntax most likely uses getters or (rather unlikely as it is a new feature) Proxies. MDN provides simple examples of how this works under the hood.
Btw: there is no such thing as "native" JS preprocessor. There are compilers like Babel or TypeScript's compiler, but they are separate projects, not related to the vanilla JavaScript.
I know that feature detection works for sniffing objects and methods (things like JSON, querySelector,...) but what about new syntax? like default function parameters?
The problem is that they cause a syntax error that cannot be caught.
Any insight on this? apart from browser and version sniffing which is mostly unreliable.
And if there is no way, does this mean we can not use new features! what are they for then (maybe for use after 10 years !)
Try to create a function within a try-catch block.
var code = '"forgotten close quote';
var valid = true;
try {
new Function(code);
}catch(exc) {
valid = false;
}
Here, trying to put "forgotten close quote into a function will fail due to a syntax error, which is then caught and will set valid to false.
As icktoofay demonstrates, there are ways to check for syntactical features without causing a syntax error, but even if you do that, what would you do with that information? You would need to have multiple versions of your code depending on the supported syntax features and need to do dynamic loading of your scripts for no real purpose.
To address your last question, you don't necessarily have to wait to use the new features. You can use a JavaScript-next to JavaScript-of-today compiler like traceur-compiler, or Typescript, which includes future JavaScript features and compiles into browser-friendly JavaScript.
There is no reliable way to check general support for syntax errors.
However there is plenty that can be used in NodeJS, today.
Also, there's nothing preventing you from using a transpiler, like Traceur, to write fancy JS and have it come out ES5-compatible on the other side.
I use Notepad++ for web-development. I was coding in JavaScript when I found this weird thing. I named a variable as private (I knew it wasn't a reserved keyword in JavaScript). But as I typed, it turned blue (all the JavaScript keywords are shown blue in Notepad++). So I thought there'll also be public, class and protected keywords. And to my surprise, they also turned blue! So does it mean JavaScript has class-based object-oriented model along with the prototypical model? I checked the following code -
public class Foo {
private bar;
}
But the console said - SyntaxError: Unexpected reserved word.
Question - Does JavaScript support class-based object-oriented model or is it just a bug in Notepad++ or my syntax is wrong?
It is a reserved keyword so that in future, this feature could be added without breaking existing code.
If you allowed private, then adding private feature to the language later would break any code that was using private as a normal identifier.
private and public are Java keywords and are reserved by JavaScript.
class is an ECMAScript reserved word.
For OO class based implementations in JavaScript, please see here
I was having issues with some jquery and posted about it here. After following a few of the suggestions, I was able to isolate the problem - IE8 did not like the variable name new_email. In fact the debugger had been telling me that the issue was at character 4 of that line, but I couldn't believe it was the variable name, so I kept looking for other issues.
After finally giving in and changing the variable name to newEmail, IE8 no longer blows up - the code works as expected with no errors.
I've been unable to find any documentation stating that you can't use underscores in jquery variable names, and indeed, the code worked correctly in every other browser with the underscore in place. Is this an unwritten rule in IE8? Is it something that real jquery developers just know? I'm worried if this really is true, as I inherited this code, and the app is enormous - I know there are several dozen variables in various places that have underscores in them.
This is actually a javascript variable and not a jQuery variable, an important distinction, and in Javascript the underscore is a valid character for variable names. You must have changed something else unrelated.
Is it possible that variable name was already assigned elsewhere? Also note that you aren't using the var keyword which can cause further issues with scope.
You can always post a jsfiddle.net example if you would like more assistance though.
here is a working jsfiddle that uses your variable
please note that you should probably be more specific than ":text"
jQuery is written in JavaScript, which is a language based on the ECMAScript Language Specification (PDF). The specification states that "underscore[s] are permitted anywhere in [a variable name]".
Your problem, as HurnsMobile, stated is most definitely not with the underscore but some other part of your code. It may also be caused by some quirk or bug in IE8 but even IE8 should be able to handle simple variable names.