File 1
var M = function (speech) {
"use strict";
document.getElementById("speech").innerHTML = speech.toString();
};
File 2
$("#test").click(function () {
M("hello");
});
JS lint probelms v
http://puu.sh/j8AOo/a24a88825b.png
'M' was used before it was defined.
This error is because you're defining M as a global variable in one file, and attempting to invoke it in another. Because global variables are often a sign of code-smell, JSLint makes you specifically declare them. There are a few options to do this. For one, you could prepend File 2 with /*global M*/, and it should stop complaining.
Missing 'new'.
This is based on variable conventions. In JavaScript, we typically only name constructor functions using CamelCase. Because constructor functions are intended to be called with the new keyword, it's detecting this as an error. In this case, your best option is probably to just rename M to m.
For more information on configuration and other JSLint help topics, see this page. Alternatively, if you have any say at all in the matter, I would strongly suggest checking out JSHint instead.
Related
Working in ReactJS, I run into an issue where imported functions that are 'unused' are failing to be recognized by the program and I believe are not being added to the window.
In my case, I'm trying to be able to import functions from other files and then call them by string name.
Ex)
import {myFunction} from '../otherFile';
functionNameString = 'myFunction'
window[functionNameString]() //call function by it's string name
//ERROR: window[functionNameString] is not a function
Without changing my above syntax, I've found two ways I can resolve this:
Add the actual function to the same file as the window[functionNameString]() call
Explicitly assign the function to the window at the top of my file like window.myFunction = myFunction
I'm trying to avoid the first case to keep this file shorter, but also don't understand why I need to do the explicit assignment of the function to the window as shown in the second case (and why defining the function in the same file doesn't need this)
Overall, my question is how can I avoid this explicit assignment of and have these imported functions callable from import (or in a shorter syntax)? Assigning like so is fine for a function or two, but I'm looking at importing 15 funcs from this other file which makes things messy working in this fashion. Thanks!
Modules have their own scope, they aren't at global scope, and imports are created as bindings within the module scope, not globals. That's at least half the point of modules: to not make everything global anymore.
Overall, my question is how can I avoid this explicit assignment of and have these imported functions callable?
They are callable. myFunction() will call your function in your example code. There's no reason whatsoever for window to be involved.
If you need to refer to them by a name in a string for some reason, you can put them in an object:
const functions = {
myFunction,
// ...
};
Then functions[functionNameString]() will work.
I was experimenting to define the built-in method alert() to see what kind of error the console will throw, but instead the built-in alert() got overridden.
This is the code -
function alert(some_string) {
console.log(some_string+some_string);
}
function say() {
alert("Hello");
}
say();
The output is : HelloHello
Coming from a Java background, it would throw a compile error as :
error: method alert() is already defined
So what happened here? Did I actually override the method?
Overriding is a classical OO term which means that a child class has method with the same name as one of the classes it inherits from which is used instead of that method on the child class.
In this case, you are straight up taking the alert variable (which by default has a value of a function provided by the browser) and assigning it a new value (the function you just declared).
(That assumes you are working in the global scope. If you were in a local scope you would just be masking the variable so you would only be making alert inaccessible to other code in the same scope … and since you were writing that code too, it wouldn't be a problem because you would know if you needed the global alert and could avoid reusing its name.)
There might be hundreds of built-in functions and I might accidentally define a function with a same name as one of them, how can I check if such accidents don't happen?
There are two basic techniques for this.
Avoid creating globals
When you create a new variable, do it in as narrow a scope as possible. A common pattern is to use an IIFE to create a new scope for all the variables related to a given piece of code.
(function () {
"use strict";
function alert() {
// Locally scoped alert that doesn't get in the way
// of any variable called `alert` from the browser
// or another library
}
})();
Use namespaces
This is just a term for having a single global as the entry point to a bunch of related code. It is usually given an ALL_CAPS name that is unlikely to conflict with other code.
This allows the functions to be accessed from anywhere, like globals, without creating lots of global variables.
var MYLIBRARY;
(function () {
"use strict";
MYLIBRARY = {
alert: alert
};
function alert() { /* etc */ }
})();
Here's the problem:
I'm using JSHint in Grunt. I have a couple JS files and they'll be merged into one file in the end. But before merging, I would like to run JSHint. However, JSHint complaints some undefined variables. Here's an example:
1. JavaScript/file_one.js defines a variable: var Foo = (function (){}());
2. JavaScript/file_two.js uses that module. new Foo().
jshint: {
files: ['Gruntfile.js',
'javascript/**/*.js',
],
options: {
// some options.
}
}
JSHint complaints that Foo isn't defined in file_two.js.
Here are my goals (if possible):
1. I want to have codes in separate files. So it's possible that some variable is defined in a different file.
2. I want JSHint to check the origin JS files. I don't want to merge all JS files to one and have JSHint to check the merged one.
3. JSHint can check across all files in <%= jshint.files %> (javascript/**/*.js for example) and look for definition.
I know one work around that to put Foo as a global in options, as in this post How to tell JSLint / JSHint what global variables are already defined. But I don't want to put the variable I defined there, since every such variable is in my source files.
So my question is whether there's a way to achieve my goal 3 to tell JSHint to look for the definition in other files.
Use the following, which has the benefit of not using JSHint configuration at all.
In the first file (the file which gives the variable its initial value):
var username = "guest"; // it becomes: window.username
In the other (second, third) file(s):
var username = window.username;
Various notes:
By declaring with var, it becomes a property of the window (global) object (the window.username). Use var, so you can declare it multiple times (let can't do that).
The same can be done with functions using function expressions (not function declarations).
If the variable is an object (for example, function) or you do not need to change its value, you can also use let in the second file. Another option is to not declare it at all in the second file. In this case, use window every time you use it:
console.log(window.username);
Using this technique, it has the additional advantage that you can distinguish your "super global" variables (the ones that you declare with var and are attached to the global object - window) from the "just global" ones (that you declare with let, as you should, and are attached to the global context but not the global object).
Your goal is not achievable. JSHint will look for configuration in your .jshintrc or in your case your Gruntfile. The only other overrides you can make is locally in the individual file.
If you are relying on global variables you should disable that setting, override to specify each of the variables either in your config or each file, or put them all in a name space.
I highly recommend switching to a module pattern and disallow anything leaking into the global scope
You will need to tell JSHint in file_two.js about the globals it uses
/* global Foo, Bar */
for file_one.js you will get a message that Foo is defined but not used. So you need to tell JSHint that other files will make use of it
/* exported Foo */
I've seen the next way of writing self-invoking functions:
(function (app) {
app.foo = {
bar: function(){}
};
}(App));
Where App is a global object.
I wonder, why do we need to pass App as a param into a function? Why don't just use this:
(function () {
App.foo = {
bar: function(){}
};
}());
I see only one advantage of using the first way. If we for some reason rename the App object, then we can easily rename the param in brackets and our code will work as it works. But in case of the second way we will probably need to rename App in all places where we use it.
Are there other differences?
It means that the contents of the function – with regards to the app identifier – are agnostic to the global (or parent) scope.
One of the scenarios in which this is done is, for example, with jQuery, when you don't want to assume that the jQuery object is called $ (e.g. if no-conflict mode is on), but you do want to call it by that name. Passing it through an anonymous function like this (i.e. (function($) {})(jQuery)) allows you to generate a locally-scoped alias that doesn't interfere with the external meaning of the name $ in the parent/global scope.
The other answers explain the benefit of having a locally scoped copy. There are a few other benefits too:
As a micro-optimization it reduces scope lookups (it's less expensive to find a local var than a global one).
It can help in the minification process as all your params are reduce to single letter named vars.
It gives you a pseudo dependency management technique...in your example, you know your code is dependent on App.
For example, many libraries use the "$" character as a shortcut for their main function (e.g. JQuery). This is convenient, but can cause a clash when using multiple libraries. So, you could pass JQuery in like this:
(function($) {
// Code
var nav = $('#nav');
// More code
})(JQuery);
That way, you can still use the convenient shortcut, but you can also avoid clashes (as long as you also configure the libraries not to use the "$" shortcut).
You can also use it to redefine global variables locally to ensure they contain whay you expect:
(function($, undefined) { ... })(jQuery);
Where undefined is now the expected undefined. Also see: What is the purpose of passing-in undefined?
Most other uses are well covered in the other answers.
I'm using JSLint to verify most of my external Javascript files, but the largest amount of errors I'm getting is from functions being used before they're defined.
Is this really an issue I should worry about?
It seems Firefox, IE7 and Chrome don't care. Functions like the popular init() (which I use often) normally stick at the top as that makes sense to me (I like to pretend it's analogous to main()) will, according to JSLint, need to be pushed to the bottom of the file.
As this is the top rated google hit and other people might not be seeing it at first in the jslint tool, there is a option called "Tolerate misordered definitions" that allows you to hide this type of error.
/*jslint latedef:false*/
If you declare functions using the function keyword, you can use them before they're declared. However, if you declare a function via another method (such as using a function expression or the Function constructor), you have to declare the function before you use it. See this page on the Mozilla Developer Network for more information.
Assuming you declare all your functions with the function keyword, I think it becomes a programming-style question. Personally, I prefer to structure my functions in a way that seems logical and makes the code as readable as possible. For example, like you, I'd put an init function at the top, because it's where everything starts from.
If you're using jshint you can set latedef to nofunc, which will ignore late function definitions only.
Documentation - http://www.jshint.com/docs/options/#latedef
Example usage:
/* jshint latedef:nofunc */
noop();
function noop() {}
Hope this helps.
From jslint's website (http://www.jslint.com/lint.html), you can read about a /*global*/ directive that allows you to set variables that are assumed to be declared elsewhere.
Here is an example (put this at the top of the file):
/*global var1,var2,var3,var4,var5*/
The :true :false is not actually needed from my experience, but it looks like it's recommended from what I read on the site.
Make sure the initial global statement is on the same line as /*, or else it breaks.
To disable this warning in jshint for all files, place this in your .jshintrc file:
{
"latedef": false
}
In your .jshintrc file, set:
"latedef": "nofunc",
it is very unfortunate the latedef option was removed. This is essential when trying to create a 'class' with an interface at the top, ie,
function SomeClass() {
var self = this;
self.func = func;
function func {
...
}
}
This style is very common but does not pass jsLint because func is 'used' before being defined. Having to use global for each 'member' function is a total pain.
You can always declare the offending function at the top
eg:
var init;
.... but then you'll have to remove the "var" when you get to the true definition further down:
init = function() {
};