Javascript - Find all implicitly declared variables in directory? - javascript

I have 100+ js files in a directory in atom editor. In chrome console I get errors about many variables not being defined (only the ones I interact with on the page are the ones that show they are undefined), but the error goes away and that portion of js works when I add the var/const/let keyword before those variables.
I now understand that they are implicitly implied variables because throughout the files, some are defined like this (strict mode is on):
foo = bar; // This is an implicitly implied variable
var foo = bar; // This fixes the issue
So the solution is to add var/const/let before those variables, but I am wondering if there is any way to scan the directory of files to point out the implicitly implied variables so I can add var/const/let in front of them?
It is taking very long to navigate through all the files manually scanning for those variables to fix up or navigate the app and wait for the error to show up to fix it one by one.
Any quick solution for this (without disabling strict mode)?

You could use a linter for the directory, which will browse through all the files and raise warnings.
JSHint is a popular one, and it's pretty easy to get going with npm from the command line, or you can install it into your code editor like Atom or Sublime.
The CLI version will be more powerful, you can specify a directory for it to scan, and recursively scan all children. In your code editor, you'll usually only get warnings for the file you currently have open.

Related

Best practices for creating a "debug mode" variable for my app?

I was about to comment out blocks of code that just printed/console.logged debugging info, and I thought, why don't I create a global scope "debug" variable, and instead of commenting this code out, put an if (DEBUG == 1) {} around it?
The reason I ask is because I'm working with javascript at the moment, and my code is spread across a few .js files. If I create a DEBUG variable in app.js, I'll need to export it from app.js and require it in other files; is this consistent with best practices? Is there a better way to do what I'm thinking of?
There are many ways to do this. Most logging libraries will have levels that allow you to only output or see messages whose levels are above some minimum. Alternatively, if you're just using console.log or console.debug and content to keep those in lieu of more robust log streams, you can change the behavior of these by using your own logging library; for example, if you have a debug.js file that exports your debug() function, import/require it once in each other file and just call debug() instead of console.debug() (or you can actually reassign console.debug = debug but that will have potential side effects in any dependencies or dependent code).
In debug.js, your function can simply check an environment variable (in node.js or similar) or global variable (in the browser) or even a hard-coded flag, and immediately return (doing nothing) if you're in production or not in the mood to print debug messages.
Take a look at bunyan's log levels as an example of how a popular logging library handles this: https://www.npmjs.com/package/bunyan#levels
If you are programming the browser and you want a quick and dirty global variable, you can do window.myVar = 'whatever'.

Getting 'cannot redeclare block-scoped variable' for 'message' variable

I'm an desktop application developer trying to learn the avalanche of technologies for web programming. I decided to focus with Angular(2-4 whatever) because it seemed like the it might be around for more than a year. I'm taking a course that is focusing on TypeScript right now. I'm using Visual Studio Code (1.14.0 - I just updated it) with TypeScript version 2.4.1 (That's what it shows in the lower right corner).
The instructor is showing us how to 'transpile' with command lines (which was another mess I wasted my morning on - see tsc.cmd as opposed to tsc).
The example in question is simply this one line, the first and only line in the Visual Studio Code editor:
let message = 0;
I get the red line of error under the 'message' telling me that:
[ts] Cannot redeclare block-scoped variable 'message'.
It worked for the instructor (on his MAC) but so did the ts compiler command.
If I change it to
let messag = 0;
The error goes away. I can't find where message is a command, statement or global variable in Type Script.
It seems like I'm running the latest of node and type script. I just worry that something is not correctly installed on my machine.
I am still getting use to the idiosyncrasies of VS Code.
My issue was that I put 'archive' copies of my previous code in a subfolder not realizing that these would be loaded as part of the 'assembly'.
Don't simply close the folder! If you are looking at just a single file, the editor will turn off intellisense for typescript.
My solution was to move my archived files out from under the folder AND rename them so their extension was no longer .ts.
Is it a npm project? If not - make it one and use the features of tsconfig.json, where you can exclude files if necessary. Maybe also use GIT? You could create a template repo (with a default configuration) for cloning and then adding specific stuff.

JavaScript - Find All Global Variables Created in Files [duplicate]

I know that I can type into Chrome or FF the following command:
Object.keys(window);
but this displays DHTMLX stuff and also function names in which I'm not interested in. And it doesn't display variables in functions that have not been executed yet. We have more than 20,000 lines of JavaScript codebase, so I would prefer static code analyis. I found JavsScript Lint. It is a great tool but I don't know how to use it for displaying global vars.
So I'm searching for memory leaks, forgotten var keywords, and so on...
To do [only] what you're asking, I think you're looking for this:
for each (obj in window) {
if (window.hasOwnProperty(obj)) {
console.log(obj);
}
}
I haven't linted that code, which is unlike me, but you get the idea. Try setting something first (var spam = "spam";) and you'll see it reported on your console, and not the cruft you asked about avoiding.
That said, JLRishe is right; JSLint executes JavaScript in your browser without "phoning home", so feel free to run it. There are also many offline tools for JSLinting your code. I use a plugin for Sublime Text, for instance.
If you'd like some simplest-case html/JavaScript code to "wrap" JSLint, I've got an example here. Just download the latest jslint.js file from Crockford's repository into the same directory, and poof, you're linting with a local copy of JSLint.js. Edit: Added code in a new answer here.
Though understand that you're linting locally with that wrapper or when you visit JSLint.com. Honestly, I can say with some confidence, Crockford would rather not see our code. ;^) You download JSLint.js (actually webjslint, a minified compilation of a few files) from JSLint.com, but you execute in the browser.
(Admittedly, you're technically right -- you never know when that site could be compromised, and to be completely on the up and up, you sh/c/ould vet jslint.js each time you grab a fresh copy. It is safer to run locally, but as of this writing, you appear safe to use JSLint.com. Just eyeball your favorite browser's Net tab while running some test, non-proprietary code, and see if any phoning happens. Or unplug your box's network cable!)
Rick's answer to use "use strict"; is another great suggestion.
A great way to catch undeclared variables is to add 'use strict' to your code.
The errors will appear in the console, or you could display them in a try ... catch block:
'use strict';
try {
var i= 15;
u= 25;
} catch(ee) {
alert(ee.message);
}
I found a very good solution to list all the global variables with the jsl command line tool:
Here is the documentation
I just have to put /*jsl:option explicit*/ into each file that I want to check. Then it is enough to run ./jsl -process <someFile> | grep 'undeclared identifier'
It is also possible to use referenceFile that contains some intentional global variables /*jsl:import <referenceFile>*/ so these variables will not be listed.

Calling a function defined outside of the Javascript library

I am working on video.js library. I was trying to modify it, so that it uses a custom player instead of the HTML5 player.
So I replaced the function calls to play() etc with the calls to my custom player(say custFunc1()). These calls are defined in a separate javascript file: custPlayer.js.
So in my index.html file, I will first include the custPlayer.js file and then the built video.js file.
However the problem is that while building the video.js package using grunt, I get the error that custFunc1 is not defined and thus grunt is not able to create the video.js library.
Now I was able to find out from a colleague that adding
/* global custFunc1 */
at the beginning of the particular file in the video.js package from where I was calling custFunc1 resolves the issue. The grunt build succeeds and it works fine.
So what I want to know is:
How does this actually resolve the issue, since this is exactly like a comment in javascript, how does it treat this differently and understand that it indicating that the function definition will be present outside the library?
Is the word global some sort of keyword in javascript?
Are there other ways of achieving this apart from what I mentioned?
On a slightly different note, I wanted to ask if grunt is the rough equivalent of make ?
Your javascript is being linted as part of your grunt process, if you look at the root of your project folder you should see a file like .jshintrc or something along those lines (different depending on the linter).
Your current settings means that the linter is going through your .js files one at a time and if it comes across a variable or function from another files it's throwing the error your seeing. You can either turn off this check or add custFunc1 to an array of known global variables. In jshint you do it like so - https://github.com/gruntjs/grunt-contrib-jshint#jshintrc
{
"globals": {
"custFunc1": true
}
}
The globals will probably already be present in the file, so just add custFunc1: true to it.
Oh and to answer question 1 - the comment type syntax tells the linter to ignore it's settings for that current file, basically overriding the settings in the .jshintrc file.
2 - Yes it's a setting in jshintrc and your adding custFunc1 to it inside the file itself instead of globally in the .jshintrc file.
3 - Mentioned above.
4 - Never used maker but yes i believe its similar in that its a pre process tool

How configure jshint in a meanjs project with socket.io?

I followed exactly that tutorial (I obviously replaced the vexxhost domain name by localhost:3000 for my tests).
And while calling grunt there is an error ('io' is not defined) but the server start without any other complain.
If I correctly understood the problem, jshint scan the whole project to validate the code and he finds on reference to an undefined variable ! But 'io' is defined when the whole application starts (because the script are loaded). In fact, that error is more a warning than an error
If I am right (and I hope some people here will correct me if I am not), that bring us to my question : How refactor the code or configure jshint to avoid that warning ?
If possible I would prefer to have an explicit reference to 'io'.
By advance thank you to everyone.
EDIT
My results from that tutorial are available here on github. The problematic file is public/modules/core/services/socket.js.
There is 2 way to configure JSHint to correct that error :
if you are calling the io variable in several place of the code. JSHint is configurable in the .jshintrc file, there is a a global section where it is possible to add "io": true. With that modification, JSHint should consider io as a global variable.
Or if you only call the io variable once, you can add the comment /* global io: true */ directly in the file where you are calling it.

Categories

Resources