I try something like this:
var varr = var;
varr x = 10;
It doesn't work, for obvious reasons, but you get the idea. How do I define keywords in Javascript, like how I can in C:
#define var int
var x = 10;
The above code wouldn't work, but is there a way to do something similar in Javascript? Not that I would absolutely need to, but just wondering.
var is a reserved token by Javascript and thus cannot be used incorrectly, or as part of variable names.
When JavaScript parses our code, behind the scenes it’s converting everything into appropriate characters, then the engine attempts to execute our statements in order and as var is a reserved token it will throw Uncaught SyntaxError: Unexpected token 'var'
JavaScript doesn't allow you to use the reserved keyword as the identifier's value, What you're gonna do is a pretty clear mistake here. you defined variable and assign as value unsupported datatypes which js don't know, Learn more
var <variable-name> = <reserved-keyword>
expected value:
var <variable-name> = <value>
javascript support all datatypes which you use in C, Int, Float, String, Obj...
Example of:
var x; // declare empty variable
x = 1;
var y = "String";
var z = [];
var foo = {};
The reason why this is possible in C is because #define allows you to declare macros that are replaced in the source code before compilation. Javascript doesn't have a concept of macros so it's not a part of the language however there are tools in JS that let you add this kind of compilation step even though it's not a part of JS itself.
Babel is probably the most popular way to do this and https://github.com/kentcdodds/babel-plugin-macros is pretty useful although I'm not sure if you can use it to redefine parts of the language.
You can instead use something like https://github.com/sweet-js/sweet-core to do what you want which lets you add a pre-processor step to replace macros however like I said, JS doesn't support macros so this is a step you have to execute to generate valid Javascript.
syntax varr = function (ctx) {
return #`var`;
};
varr test = 10;
$ sjs test.sweet
var test = 10;
It's also important to mention that in C this is something that's built into the language so IDEs understand how to deal with macros, but if you're using an external tool you're not going to have a fun time using macros that redefine keywords, especially when it comes to things like syntax highlighting. This is something I'd definitely discourage, but it is technically possible if you're willing to step outside the bounds of just Javascript.
Related
Typescript is said to be an objected oriented form of javascript , allows type safety inheritance etc.
But why it does not prevent to declare same name variable as its parameter inside body of method.
This could be very problematic specially when user forget and declare a variable with same name as its parameter and this cause overriding and lost of previous value stored in that variable.
Example Typescript:
function greeter(person : Person,b="") {
var b = "3";
//No warning in this case
}
Example C#:
public void greeter(Person person ,string b="")
{
string b = "3";
//Error A local parameter name cannot be declare in sc
}
Please help , or tell me is there any method to avoid such condition in Typescript?
Whilst this works with var, it won't be allowed if using let or const. E.g. this does not compile:
function greeter(person: Person, b = "") {
const b = "3";
// Error: Duplicate identifier 'b'
}
In general, much of the JS community is moving away from var for many similar reasons, and using let & const instead will give you lots of extra safety.
If you'd like to enforce this, there are linting rules available for tslint and eslint.
Alternatively, it should be possible to write your own custom linting rule to disallow with var as well, but that will be substantially more work, and using let and const instead anyway has many other benefits.
I'm new to javascript and have picked up an application developed by another team recently.
In this program in one place where they declare several variables at once there is a missing comma like:
var me = this,
missing = this.missingComma
grid = something.Something;
What if any are the consequences of there not being a comma after the second entry. The relevant bit appears to work when just running it. The code has no tests and since it's javascript I cant compile it, also I dont really know what its supposed to do so unfortunately 'not falling over' is currently my best guess at 'does what its supposed to do'!
Why does it work? Isn't this a syntax error?
In JavaScript the semi-colons aren't required to indicate the end of a line. A linebreak is sufficient to indicate that the next line is a separate statement rather than a continuation of the previous line of code (as is the case when you use the comma to indicate multiple variables).
Your code is essentially the same as this:
var me = this, missing = this.missingComma;
grid = something.Something;
Since that declares the grid variable without the var keyword, you'd end up with grid being created in the global, rather than the current, scope. That's generally something you want to avoid but it's not going to be the end of the world if it does happen - in this case it may even be intended (though I'd guess not).
Javascript is ubiguitous with a a lot of freedom ;)
Maybe it helps you to understand some peculiarity of JS if you read some additional info about semicolons, commas and newlines in Javascript:
http://www.codecademy.com/blog/78-your-guide-to-semicolons-in-javascript
For the sake of readability, I would suggest you to use the classic approach, anyway.
var me = this;
var you = that;
or at least
var me = this, you = that;
For the rest, I think that Anthony Grist has brought it to the point.
Well even though in javascript the semicolon is not required it is a must now a days, because if you want your JavaScript to get minimized, it must have all semicolons. Minimization puts your complete JavaScript in one line... replacing long variable names with short ones, etc.
On the other hand... back to you question.
If you declare your var inside a JavaScript "namespace" (actually an object) then all the variables are "private" and you could choose to make the ones "public" by using the reveal pattern.
This is a good practice, else all you variables are declared on the windows scope... which actually can then be overwritten by any other part of your page that uses the same variable name, even if you thought it was completely independent.
So you could actually do something like this :
var MyNamespace || {}
// this delcares an object MyNamespace only if it doesn't exists yet
MyNamespace.Logic = function(){
var self = this,
myPrivateVariable = "Hello",
self.myPublicVariable = "World",
self.printHello = function(){
alert(myPrivateVariable +' ' +self.myPublicVariable );
};//this semicolon closes the var statement
};
Now you can use somehwer on you page folowing logic
var newInstanceOnMyLogic = new MyNamespace.Logic()
This is equivalent of writing
var newInstanceOnMyLogic = new window.MyNamespace.Logic();
But your variables myPrivateVariable and myPublicVariable are no longer on the windows context and can't be overwritten
Now if you write something like
alert(newInstanceOnMyLogic.myPublicVariable);
you'll get a "World"
But
alert(newInstanceOnMyLogic.myPrivateVariable );
you'll get an undefined
and
newInstanceOnMyLogic.printHello();
will get an alert of "Hello World"
I've been checking out the Google Closure Compiler recently. I downloaded the .jar file and gave it a test drive. So far, I must say that I've been very impressed. I can certainly see its usefulness beyond minimization. Props to the Google team!
I do have one small gripe though. It seems to me that you only get two options as far as optimization goes. It's either SIMPLE_OPTIMIZATIONS or ADVANCED_OPTIMIZATIONS. The former, although adequate, is very simple IMHO. For one thing, unless I'm missing something, it leaves all property names untouched. It also does not remove unreachable code. On the other hand, the latter option is simply too destructive.
Now, I'm fairly new to JavaScript, so it's very probable that I'm missing something. If I say something stupid, feel free to school me. That said, I can understand the issues with renaming in JavaScript. The Google team recommends using the bracket notation (object['property']) instead of the dot notation (object.property) to access the properties that you do not want changed and never mixing the two uses. They also suggest 'exporting' methods by using the following pattern:
MyClass = function(name) {
this.myName = name;
};
MyClass.prototype.myMethod = function() {
alert(this.myName);
};
window['MyClass'] = MyClass; // <-- Constructor
MyClass.prototype['myMethod'] = MyClass.prototype.myMethod;
However, there are legitimate cases that you want to mix the two notations. Let's say we are building a game. The game's code is completely isolated inside a closure. It does not 'export' anything to the global scope, nor does it need to. In fact, it really should not touch the window object. However, it does need to read some in-game properties from XML configuration files.
Sample JavaScript:
var TheGreatAdventure = (function(window) {
function Fighter() {
// Private to application
this.id = 42;
// Accessible to XML configuration system
this.name = 'Generic Jen';
this.hitPoints = 100;
this.onAttack = genericFighterAttack;
this.onSpeak = genericFighterSpeak;
...
}
Fighter.publishedProperties = ['name', 'hitPoints', 'onAttack', 'onSpeak']
function genericFighterAttack() {...}
function genericFighterSpeak() {...}
function cassieAttack() {...}
function cassieSpeak() {...}
...
EntityReader = {
...
function readFromXMLNode(attributes, entityClass, entityInstance) {
for (var i = 0; i < attributes.length; i++) {
var attribute = attributes[i];
if (attribute.nodeName in entityClass.publishedProperties)
entityInstance[attribute.nodeName] = bindContext[attribute.value];
}
}
...
}
}(window));
Sample XML configuration file:
<Fighter name='Custom Cassie' onAttack='cassieAttack' onSpeak='cassieSpeak'/>
Not only would the above system fail to assign the properties, the functions cassieAttack and cassieSpeak would have been eliminated during minimization as dead code!
Now, there's no way I'm accessing all of the 'published' properties using the bracket notation throughout the game's code. Even if there's no run-time penalty in doing so (there should not be any), there's still a lot of extra typing involved and it's (IMO) an eyesore. With such common properties, everything would show up as a string inside a text editor, defeating the purpose of syntax highlighting!
It seems to me that a simple #preserve (or something similar) directive over those properties would allow ADVANCED_OPTIMIZATIONS to be used with minimum cost in final program size. Am I missing something?
This answer was completely rewritten, turns out there's a way to do what user1127813 wants.
You need to provide a property mapping file that maps some names to themselves, using the --property_map_input_file flag. Suppose you have the following original code in test.js:
/** #constructor */
function Fighter() {
this.ID = 42;
this.fullName = 'Generic Jen';
this.hitPoints = 100;
}
Fighter.publishedProperties = ['fullName', 'hitPoints'];
var jen = new Fighter();
var bob = new Fighter();
bob.ID = 54;
bob.fullName = 'Bob the Destructor';
bob.hitPoints = 1337;
for(i = 0; i < Fighter.publishedProperties.length; i++) {
prop = Fighter.publishedProperties[i];
alert(prop + ' = ' + bob[prop]);
}
Compile it like so:
java -jar closure-compiler.jar --compilation_level ADVANCED_OPTIMIZATIONS --js test.js --property_map_output_file testprop.txt --js_output_file test2.js
You will get a new file test2.js (with contents that don't work) and another file testprop.txt that contains:
ID:a
hitPoints:c
fullName:b
Change testprop.txt so it looks like this:
ID:ID
hitPoints:hitPoints
fullName:fullName
Then recompile with testprop.txt as input instead of output:
java -jar closure-compiler.jar --compilation_level ADVANCED_OPTIMIZATIONS --js test.js --property_map_input_file testprop.txt --js_output_file test2.js
Observe the contents of test2.js:
var a=["fullName","hitPoints"],b=new function(){};b.ID=54;b.fullName="Bob the Destructor";b.hitPoints=1337;for(i=0;i<a.length;i++)prop=a[i],alert(prop+" = "+b[prop]);
The desired properties are now accessed with their original name using the dot notation and the program will correctly show popups with the published properties of bob.
The compiler has support for this, but it is awkward, and depends on a "primitive" from the Closure Library called "goog.reflect.object":
/** #nocollapse */
Fighter.publishedProperties = goog.object.transpose(goog.reflect.object(
Fighter, {fullName:1, hitPoints:2}));
This avoid the use of quoted properties. If this is the only thing that you use from the Closure Library everything but the "goog.object.transpose" function will be compiled out (goog.object.transpose isn't special so you are free to use an alternate implementation). This is type safe and can be used with the compiler's type based optimizations (see a discription of that here: http://code.google.com/p/closure-compiler/wiki/ExperimentalTypeBasedPropertyRenaming ).
The key is that goog.reflect.object must be used directly, taking the constructor and an object literal with the keys of the properties you need to preserve.
The other thing that you will want to be aware of this that in ADVANCED mode, if Fighter.publishedProperties is defined in global scope, it will be removed from the constructor due to namespace collapsing. #nocollapse prevents this. An alternative would be to use a helper method to add the property:
function addPublishedProperties(obj, value) {
obj.publishedProperties = goog.object.transpose(value);
}
Ok, I've covered a lot of ground here so be sure to let me know if you would like clarification.
I've recently tested UglifyJS and YUI Compressor and noticed something odd.
Both minifiers don't seem to change the names of object properties, only the names of variables and functions.
for instance if I have the following code:
var objName = {first:2, second:4};
alert(objName.first + " " + objName.second);
the names first and second remain unchanged in the minified version.
Why is that?
Since in javascript a new scope is created in a function, you can scope your code in an immediately invoked function.
// scoped
(function() {
var objName = {first:2, second:4};
alert(objName.first + " " + objName.second);
})();
Then using Google's Closure Compiler, if you turn on the "Advanced" optimization it will see that the properties are only used locally, and will obfuscate them.
// result
var a={a:2,b:4};alert(a.a+" "+a.b);
It's because it doesn't know where the object is going to be used. It could be used externally by other code and you wouldn't want your other code to have to change whenever you obfuscate it.
Edit So basically, it's like that to prevent obfuscation from breaking external/internal references to properties that may not be possible to figure out while obfuscating.
Since there are no well defined scoping rules around objects in JavaScript it's impossible to obfuscate the names in a way that is guaranteed to be correct.
For example, if you had the following function:
function f() {
return { first: 'foo', second: 'bar' };
}
In order to obfuscate the property names you would have to nail down all the places that f is called from. Since functions are first-class in JavaScript they can be assigned and passed around in arbitrary ways making it impossible to pin down where f is referenced without actually running the program.
Additionally, JavaScript doesn't have any way for you to specify intent around what's public API and what isn't. Even if the minimizer could reliably determine where the function is called from in the code you give it, there would be no way for it to make the same changes to code that it hasn't seen.
I guess that's because the minifiers would break the object properties. Consider this:
function getProp(ob,name) {
return ob[name];
}
var objName = {first: 2, second: 4};
var prop = getProp(objName, "second");
There's no way for the minifier to know the string literal "second" being an object property. The minified code could look like this then:
function a(b,c){return b[c]}var d={p1:2,p2:4};var e=a(d,"second")
Broken now.
The latest release of uglify (today) has object property mangling, see v2.4.19. It also supports reserved files for excluding both object properties and variables that you don't want mangled. Check it out.
The only public tool so far to obfuscate property and function names (afaik) is the Closure Compiler's Advanced mode. There are a lot of limitations and restrictions, but the end result is generally worth it.
As a passing note: the Dojo Toolkit is compatible (with some minor modifications) with the Closure Compiler in Advanced mode -- arguably the only large-scale public JavaScript library that can be fully obfuscated. So if you are looking at obfuscation to protect your IP, you should look into using Dojo for the task.
http://dojo-toolkit.33424.n3.nabble.com/file/n2636749/Using_the_Dojo_Toolkit_with_the_Closure_Compiler.pdf?by-user=t
Stephen
What about doing something like:
// scoped
(function() {
var objName = {first:2, second:4};
var vA = 'first';
var vB = 'second';
alert(objName[vA] + " " + objName[vB]);
})();
Once objName.first and/or objName.second are referenced enough times, this technique will start to save characters. I can't think of any reason that wouldn't work, but I can't find any minifiers that do it.
What are the differences and/or advantages, if any, of using commas when declaring a group of variables rather than semicolons.
For example:
var foo = 'bar', bar = 'foo';
versus
var foo = 'bar';
var bar = 'foo';
I know that if you specify the var keyword on the first variable in the first example it persists across all of the variables, so they both produce the same end result regarding scope. Is it just personal preference, or is there a performance benefit to doing it either way?
No performance benefit, just a matter of personal choice and style.
The first version is just more succinct.
Update:
In terms of the amount of data going over the wire, of course less is better, however you would need a hell of a lot of removed var declarations in order to see a real impact.
Minification has been mentioned as something that the first example will help with for better minification, however, as Daniel Vassallo points out in the comments, a good minifier will automatically do that for you anyways, so in that respect no impact whatsoever.
After reading Crockford and others, I started to chain my variables with comma exclusively. Then later, I really got annoyed by the Chrome DevTools debugger that wouldn't stop at variable definitions with comma. For the debugger, variable definitions chained with comma are a single statement, while multiple var statements are multiple statements at which the debugger can stop. Therefore, I switched back from:
var a = doSomethingA,
b = doSomethignB,
c = doSomethingC;
To:
var a = doSomethingA;
var b = doSomethignB;
var c = doSomethingC;
By now, I find the second variant much cleaner, not to mention its advantage of solving the debugger issue.
The "less code through the wire" argument is not persuasive, as there are minifiers.
I prefer the var-per-variable notation:
var a = 2
var b = 3
because the other comma-instead-of-another-var notation have these three shortcomings:
1. Hard to maintain
Consider this code:
var a = 1,
b = mogrify(2),
c = 3
But hey, what does the mogrify do? Let's print b to find out:
var a = 1,
b = mogrify(2),
console.log(b)
c = 3
breaks stuff
2. Hard to read
The var in the begging of the line clearly communicates that there will be a new variable initiated.
var get_all_unicorn_promise = db.get_all_unicorns((unicorn) => {
unicorn.legs.map((leg) => {
leg.log('yes')
})
}).sort(),
c = 3
What the hell is the c = 3 doing there right?
3. Not consistent
Consider this:
var a = 1,
b = 2,
c = 3
With var-per-variable every declaration follow the same structure. With comma-instead-of-another-var the first variable is declared in different way than others. If you decide to, say, move the first variable inside a for cycle, you will have to add var to the middle of declarations
Other than preference, it seems like majority of notable projects use the var-per-variable notation
I agree with the other answerers that this is mainly a matter of personal style. But to bring an "Authoritative" opinion into the discussion, this is what Douglas Crockford says on the website of the popular JSLint tool:
But because JavaScript does not have block scope, it is wiser to declare all of a function's variables at the top of the function. It is recommended that a single var statement be used per function. This can be enforced with the onevar option.
As others have noted, it is a style preference. JSLint might tell you to only have one var per function (if you use the "Good Parts"). Thus if using JSLint to check your code (not a bad idea, IMHO), you'll end up using the first format more than the latter.
On the other hand, the same author, Douglas Crockford, says to put each variable in its own line in his coding conventions. So you may want to uncheck the "All one var per function" checkbox in JSLint if you use it. ;-)
I don't think there's any noticeable difference, as far as I'm concerned it's just personal preference.
I hate having multiple var declarations so I usually do:
var
one
,two
,three
,four
;
As it's shorter and arguably more readable, no var noise to look at.
Since I don't see any references to it, here is a link to the ECMA-262 specification, which is the underlying spec for JavaScript. The grammar from that page says:
12.2 Variable Statement
Syntax
VariableStatement :
var VariableDeclarationList ;
VariableDeclarationList :
VariableDeclaration
VariableDeclarationList , VariableDeclaration
VariableDeclarationListNoIn :
VariableDeclarationNoIn
VariableDeclarationListNoIn , VariableDeclarationNoIn
VariableDeclaration :
Identifier Initialiseropt
VariableDeclarationNoIn :
Identifier InitialiserNoInopt
Initialiser :
= AssignmentExpression
InitialiserNoIn :
= AssignmentExpressionNoIn
What you can glean from this is using commas or not doesn't matter. Either way, it ends up being parsed as a VariableDeclaration and is treated exactly the same. There should be no difference to how the script engine treats the two declarations. The only differences would be ones already mentioned in other answers - saving more space and practically immeasurable differences in the amount of time it takes to apply the grammar to find all the VariableDeclarations when the script is compiled.
The first saves a few characters--so there is a very small saving in terms of the JS filesize and therefore bandwidth consumption. The only time this would become noticable would be in extreme cases.
I prefer the second version (each has its own var). I think that's because I come from a C++ background. In C++, you can declare variables like you do in your first example, but it is frowned upon (it easily leads to mistakes when you're trying to create pointers that way).
If you are minifying your javascript, there is a fairly large benefit:
var one, two, three, four;
becomes
var a, b, c, d;
Where as
var one;
var two;
var three;
var four;
becomes
var a;
var b;
var c;
var d;
That's an additional three instances of var, which can add up over time.
See The "A List Apart" article series "Better Javascript Minification" Part 1 and Part 2