I checked out a github project recently, and I found the following code in one of the files:
var fu = $('#fileupload').data('blueimpFileupload'),
template;
It seems like this is assigning one variable to two values. What is it actually doing? Someone in my office mentioned that it may be the equivalent of just saying:
var f = $('#some-id').data('string');
var template;
Is this the case?
Your colleague is correct: you are declaring two variables, and assigning only to the first. The two statements are equivalent.
The declaration is not uncommon, quite common in fact, its a requirement of JSLint, to have a single var , and all the variables declared at the top as it would be done by hoisting anyways (but not necesserily in a single line).
On the other hand, there's a well accepted convention for declaring the variables in separate lines, sorted alphabetically. The declaration you see is passing JSLint check and adhering to convetion
Related
This is related to, but in my mind not a duplicate of, Passing named arguments to a Javascript function [duplicate] and Named parameters in javascript.
Various answers and comments on those questions propose approaches to deal with the lack of JavaScript language support for named arguments.
The original poster's concern was this:
Calling a Javascript function with something like
someFunction(1, true, 'foo');
is not very clear without familiarity with the function.
Let's say someFunction is declared elsewhere in the code as:
function someFunction(numberOfClowns,wearingHat,screamingAtTopOfLungs) {
console.log(arguments)
}
Is there any particular reason why you couldn't call the function like this?
someFunction(numberOfClowns=1, wearingHat=true,screamingAtTopOfLungs='foo')
From my preliminary testing, this seems to not result in any errors, and certainly addresses any issues of clarity.
I guess you would need to var all of the variables beforehand, and be aware that variable assignment is occurring, so not be too surprised that numberOfClowns is now equal to 1. Anything else that I'm not considering?
Since you're just using the assignments as labels anyway, why not simply use comments?
someFunction(/*numberOfClowns=*/1, /*wearingHat=*/true, /*screamingAtTopOfLungs=*/'foo')
I've seen this done in C code (particularly for functions with 5 or more arguments), and it would avoid the nasty side-effects you mention.
Since there aren't actually any checks being done with the var-assignment version, this seems to have all the same benefits without the downsides.
I guess you would need to var all of the variables beforehand, and be aware that variable assignment is occurring
This is a major problem in my eyes. It makes this a whole more complicated than any of the other approaches, and it's not a local solution - you're polluting your scope.
Anything else that I'm not considering?
The main argument of named parameters/named arguments is that you can order and omit them however you want, and the right values will still end up in the right variables. Your approach does not provide this. Better just use objects as everyone does.
I'd wager there will be more problems than without the assignments.
As you say, assignments return the assigned value, so if the variables are properly declared, there is no problem. To avoid conflicts with other code in the same function, I suggest wrapping the call inside a block, and declaring the parameters with let.
function someFunction(numberOfClowns, wearingHat, screamingAtTopOfLungs) {
console.log(numberOfClowns, wearingHat, screamingAtTopOfLungs);
}
{
let numberOfClowns, wearingHat, screamingAtTopOfLungs;
someFunction(numberOfClowns=1, wearingHat=true, screamingAtTopOfLungs='foo');
}
You may also be interested in destructuring objects:
function someFunction({numberOfClowns, wearingHat, screamingAtTopOfLungs}) {
console.log(numberOfClowns, wearingHat, screamingAtTopOfLungs);
}
someFunction({numberOfClowns: 1, wearingHat: true, screamingAtTopOfLungs: 'foo'});
In python _ is used as a throwaway variable. Is there an idiomatic accepted name in javascript?
Rigth now, you can use array destructuring, no need for a var.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment
For example:
[,b] = [1,2];
console.log(b);
will output :
2
And the value 1 won't be assigned to any unused var.
There isn't an accepted throwaway variable naming in JavaScript like in Python. Although, generally in the software engineering world, engineers tend to call those variables:
dummy, temp, trash, black_hole, garbage.
Use these variable namings or whatever name that will imply to the engineer reading your code that these variables have no specific use.
With that in mind, I would strongly not recommend using signs such as below as a throwaway variable:
_, $
Unless there is an explicit convention like in Python, don't use these signs as a throwaway variable, otherwise, it may interfere with other naming conventions and libraries in other languages, like the underscore and the jQuery libraries in JS.
And of course, if you find a specific use for that variable later on, make sure to rename it.
Generally, you will declare the signature of a function as an array. Simply omit one of them
const foo = (bar,baz,) => bar+baz;
foo(3,4,5) // → 7
This obviously works as long as the declaration of function argument is the last one; unlike this answer, which is valid for already-declared variables embedded in arrays. This:
const foo = (, bar,baz) => bar+baz;
will fail with:
Uncaught SyntaxError: expected expression, got ','
You can hack your way into this using any expression. However, you'll need to use the self same expression in every invocation
const quux = ([], bar,baz) => bar+baz;
quux(42,3,4); // → Uncaught TypeError: (destructured parameter) is not iterable
quux([],3,4); // → 7
That constant can be anything, so you can as well call it "dummy", but you will still have to repeat in every invocation.
Reading Crockfords The Elements of JavaScript Style I notice he prefers defining variables like this:
var first='foo', second='bar', third='...';
What, if any benefit does that method provide over this:
var first='foo';
var second='bar';
var third='...';
Obviously the latter requires more typing but aside from aesthetics I'm wondering if there is a performance benefit gained by defining with the former style.
Aside of aesthetics, and download footprint, another reason could be that the var statement is subject to hoisting. This means that regardless of where a variable is placed within a function, it is moved to the top of the scope in which it is defined.
E.g:
var outside_scope = "outside scope";
function f1() {
alert(outside_scope) ;
var outside_scope = "inside scope";
}
f1();
Gets interpreted into:
var outside_scope = "outside scope";
function f1() {
var outside_scope; // is undefined
alert(outside_scope) ;
outside_scope = "inside scope";
}
f1();
Because of that, and the function-scope only that JavaScript has, is why Crockford recommends to declare all the variables at the top of the function in a single var statement, to resemble what will really happen when the code is actually executed.
Since JavaScript is generally downloaded to the client browser, brevity is actually quite a valuable attribute. The more bytes you have to download, the slower it gets. So yes, there is a reason apart from aesthetics, if not a massive one.
Similarly, you'll see people preferring shorter variable names to longer.
Personally, I don't bother minimising whitespace, as there are minimisers that can do this sort of thing for you (for example in YUI), and lack of indentation and spacing leads to less maintainable code.
No difference in semantics and no measurable difference in performance. Write whichever is clearest.
For simple examples like:
var first= 'foo', second= 'bar', third= 'bof';
the concise single-statement construct is probably a win for readability. On the other hand you can take this much too far and start writing half your program inside a single var statement. Here's a random example plucked from the jQuery source:
var name = match[1],
result = Expr.attrHandle[ name ] ?
Expr.attrHandle[ name ]( elem ) :
elem[ name ] != null ?
elem[ name ] :
elem.getAttribute( name ),
value = result + "",
type = match[2],
check = match[4];
I find this (by no means the worst example) a bit distasteful. Longer examples can get quite hard to read upwards (wait, I was in a var statement?) and you can end up counting the brackets to try to work out what's a multi-line expression and what's just an extended var block.
I believe that what he is going for is declaring all variables as abosultely the first statement in a function (You'll notice that JSLint complains about this if you use it and don't declare them on the first line). This is because of JavaScript's scope declaration limitations (or quirks). Crockford emphasizes this as good practice for maintainable JavaScript code. The second example declares them at the top, but not in the first execution statement. Personally, I see no reason as why to prefer the first over the second, but following the first does enforce that all variables are declared before doing anything else in the function.
David is right that the larger the script the more time it will take to down load, but in this case the difference between the two is minimal and can be handled by using YUI compress etc.
It's a personal programming style choice.
On the one hand there is readability, wherein placing each variable declaration on a separate line makes it more obvious what's going on.
On the other hand, there is brevity, wherein you're eliminating transmitting a few extra bytes over the network. It's generally not enough to worry about, unless you're dealing with slow networks or limited memory on the client browser side.
Brevity is also known as laziness on the part of the programmer, which is one reason that many purists avoid it.
It all comes down to personal taste or a set of style-guides, your development team follows. If you are serving JavaScript yourself, you usually compress or minify your script(s) into one long string in one single file. So the whole you-are-saving-bytes-and-your-scripts-download-faster argument is, well, not an argument :)
I usually declare my variables like this: (a style you didn't mention)
var something,
somethingElse,
evenMoreSomething,
andAnotherThing;
A statement like "var" is not minified/compressed.Every time you place a var, instead of a comma you lose 4 chars, if I count right.
I came across to Ext.namespace() in the project that I am working on.
I looked in Sencha's website and the explanation was not very helpful.
This is what they are saying:
Creates namespaces to be used for scoping variables and classes so
that they are not global. Specifying the last node of a namespace
implicitly creates all other nodes.
Ext.namespace('Company', 'Company.data');
They also mention that Ext.ns('Company.data') is preferable.
I apologize if this question seems simple or dumb, but I really want to completely understand this concept. Thanks in advance
This is what is not very clear to me:
If I have Ext.namespace('Company', 'Company.data') at the top of my JS page, does this mean that it carries all the other function name and variables (like a global scope)?
What exactly 'Company' and 'Company.data' stand for in Ext.namespace('Company', 'Company.data')?
Why new convention Ext.ns('Company.data') does not have 'Company' like in Ext.namespace?
What does this mean Specifying the last node of a namespace implicitly creates all other nodes?
When exactly this idea should be used?
First off, this is what Ext.ns('Company.data') is roughly equivalent too:
if (!Company) var Company = {};
if (!Company.Data) Company.Data = {};
Basically, it is just a shortcut for defining deeply nested structures
of objects. It is useful if your project structures this way; I've seen
projects with a Java backend that duplicate the
com.company.app.data.package package names in JavaScript, for which
Ext.ns is a nice shortcut.
Addressing your questions point by point:
If I have Ext.namespace('Company', 'Company.data') at the top of my JS page, does this mean that it carries all the other function name and variables (like a global scope)?
No. You have to add to Company.Data, like Company.Data.newVal = 5;.
What exactly 'Company' and 'Company.data' stand for in Ext.namespace('Company', 'Company.data')?
They are names, chosen by you, following your projects convention.
Why new convention Ext.ns('Company.data') does not have 'Company' like in Ext.namespace?
Because 'Company' is implied. That is, Ext.ns('Company',
'Company.data') is like:
if (!Company) var Company = {};
if (!Company) var Company = {};
if (!Company.Data) Company.Data = {};
This makes it easier to see why the first 'Company' is redundant.
What does this mean Specifying the last node of a namespace
implicitly creates all other nodes?
When exactly this idea should be used?
I answered these two above.
Ext.namespace is really only useful if you want to define your own classes without using Ext.define.
The example below requires the namespaces to be created ahead of time:
Company.data.Form = Ext.extend(...); //this is the old way of defining classes
The standard way for creating ExtJS classes is:
Ext.define('Comany.data.Form', {...});
This method creates the namespaces for you automatically.
To create an IDE that would autocomplete all variables the user declares but would be oblivious to other variables such as Math.PI or even the module Math, the IDE would need to be able to identify all identifiers relating to variables declared by the user. What mechanism could be used to capture all such variables, assuming you already have access to the AST (Abstract Symbol Table) for the program?
I am using reflect.js (https://github.com/zaach/reflect.js) to generate the AST.
I think it's pretty much impossible
Here is why I think it's pretty much impossible without executing it:
Let us go through the unexplored parts, from easy to hard.
Easy to catch:
Function scope is missed here:
(function(x){
//x is now an object with an a property equal to 3
// for the scope of that IIFE.
x;
})({a:3});
Here is some fun dirty tricks for you all.:
Introducing... drum roll... Block Scoping!!
with({x:3}){
x;//x is now declared in the scope of that with and is equal to 3.
}
try{ throw 5}catch(x){
x // x is now declared in the scope of the try block and is equal to 5;
}
(people reading: I beg you to please not use these last two for actual scoping in code :))
Not easy:
Bracket notation:
var n = "lo";
a["h"+"e"+"l"+n] = "world"; // need to understand that a.hello is a property.
// not a part of the ast!
The really hard parts:
Let us not forget invoking the compiler These would not show up in the AST:
eval("var x=5"); // declares x as 5, just a string literal and a function call
new Function("window.x = 5")();// or global in node
In node.js this can also be done with the vm module. In the browser using document.write or script tag injection.
What else? Of course they can obfuscate all they want:
new Function(["w","i","n","dow.x"," = ","5"].join(""))(); // Good luck finding this!
new Function('new Function(["w","i","n","dow.x"," = ","5"].join(""))()')();// Getting dizzy already?
So what can be done?
Execute the code, once, in a closed, timed environment when you update the symbol table (just the relevant parts)
See what's the generated symbol table is from the execution
Boom, you got yourself a symbol table.
This is not reliable but it's probably as close as you get.
The only other alternative I can think of, which is what most IDEs are doing is to simply ignore anything that is not:
object.property = ... //property definition
var a = ... //scoped
b = ... //global, or error in strict mode
function fn(){ //function declaration
object["property"] //property with a _fixed_ literal in bracket notation.
And also, function parameters.
I have seen no IDE that has been able to deal with anything but these. Since they're the most common by far, I think it's perfectly reasonable to count those.
By adding them onto am object that already exists....ie
window.mynewvar = 5;
function mynewfunc() {
}