A small test app is set up like this:
init.js:
//#codekit-prepend "vendor/jquery-1.7.2.js"
//#codekit-prepend "vendor/underscore.js"
//#codekit-prepend "vendor/backbone.js"
// Setup namespace for the app
window.app = window.app || {};
//#codekit-append "models/Ride.js"
Ride.js:
(function() {
window.app.Ride = Backbone.Model.extend({
initialize: function() {
console.log("Ride initialized");
}
});
})();
CodeKit's JSHint check reports that both Backbone and console are not defined. What am I missing here?
JSHint doesn't run your code so it doesn't know about any modules you included in other files. You have to specifically tell it about all global variables you plan to use in Ride.js. In your case it will be: /*global Backbone */. console is disallowed by default because it is not a very good idea to ship your software with filled console.log calls. To remove this warning you can use /*jshint devel:true */.
So in the end your file should look like this to pass JSHint check:
/*jshint devel:true */
/*global Backbone */
(function() {
window.app.Ride = Backbone.Model.extend({
initialize: function() {
console.log("Ride initialized");
}
});
})();
More info here: http://www.jshint.com/options/
Bryan here. CodeKit does check your files in a full, global context. (That is, it combines them first, so variables declared in an earlier file will be valid in a later one. This assumes you use CodeKit to combine the files, either with #codekit-prepend/append statements or drag/drop import links set up in CodeKit itself). If you're combining your JS files some other way (such as a build script) then CodeKit is unaware that the files go together and therefore it checks each one separately.
You can use the comment flags in the answer above, or you can configure JSHint's options directly in CodeKit. See the preferences window (or project settings area, if your project uses project-level settings). You can also enter custom globals there as well, which will remove those warnings.
Cheers!
Related
I include the statement:
"use strict";
at the beginning of most of my Javascript files.
JSLint has never before warned about this. But now it is, saying:
Use the function form of "use strict".
Does anyone know what the "function form" would be?
Include 'use strict'; as the first statement in a wrapping function, so it only affects that function. This prevents problems when concatenating scripts that aren't strict.
See Douglas Crockford's latest blog post Strict Mode Is Coming To Town.
Example from that post:
(function () {
'use strict';
// this function is strict...
}());
(function () {
// but this function is sloppy...
}());
Update:
In case you don't want to wrap in immediate function (e.g. it is a node module), then you can disable the warning.
For JSLint (per Zhami):
/*jslint node: true */
For JSHint:
/*jshint strict:false */
or (per Laith Shadeed)
/* jshint -W097 */
To disable any arbitrary warning from JSHint, check the map in JSHint source code (details in docs).
Update 2: JSHint supports node:boolean option. See .jshintrc at github.
/* jshint node: true */
If you're writing modules for NodeJS, they are already encapsulated. Tell JSLint that you've got node by including at the top of your file:
/*jslint node: true */
I'd suggest to use jshint instead.
It allows to suppress this warning via /*jshint globalstrict: true*/.
If you are writing a library, I would only suggest using global strict if your code is encapsulated into modules as is the case with nodejs.
Otherwise you'd force everyone who is using your library into strict mode.
I started creating a Node.js/browserify application following the Cross Platform JavaScript blog post. And I ran into this issue, because my brand new Gruntfile didn't pass jshint.
Luckily I found an answer in the Leanpub book on Grunt:
If we try it now, we will scan our Gruntfile… and get some errors:
$ grunt jshint
Running "jshint:all" (jshint) task
Linting Gruntfile.js...ERROR
[L1:C1] W097: Use the function form of "use strict".
'use strict';
Linting Gruntfile.js...ERROR
[L3:C1] W117: 'module' is not defined.
module.exports = function (grunt) {
Warning: Task "jshint:all" failed. Use --force to continue.
Both errors are because the Gruntfile is a Node program, and by default JSHint does not recognise or allow the use of module and the string version of use strict. We can set a JSHint rule that will accept our Node programs. Let’s edit our jshint task configuration and add an options key:
jshint: {
options: {
node: true
},
}
Adding node: true to the jshint options, to put jshint into "Node mode", removed both errors for me.
Add a file .jslintrc (or .jshintrc in the case of jshint) at the root of your project with the following content:
{
"node": true
}
There's nothing innately wrong with the string form.
Rather than avoid the "global" strict form for worry of concatenating non-strict javascript, it's probably better to just fix the damn non-strict javascript to be strict.
process.on('warning', function(e) {
'use strict';
console.warn(e.stack);
});
process.on('uncaughtException', function(e) {
'use strict';
console.warn(e.stack);
});
add this lines to at the starting point of your file
I think everyone missed the "suddenly" part of this question. Most likely, your .jshintrc has a syntax error, so it's not including the 'browser' line. Run it through a json validator to see where the error is.
This is how simple it is: If you want to be strict with all your code, add "use strict"; at the start of your JavaScript.
But if you only want to be strict with some of your code, use the function form. Anyhow, I would recomend you to use it at the beginning of your JavaScript because this will help you be a better coder.
How can I set the scope of the defined variables for JSHint to my whole project in WebStorm?
If I have multiple files and imports like jquery or Backbone I don't need to see the error JSHint: 'Backbone' is not defined.(W117). This is not only form my imported libraries, but also for my own external files.
Some suggestions is that I should disable undefined errors, but this is the functionality that I want to use.
I.E.
In my main.js I have this:
function Main(){
// Some epic code
}
Main.prototype.theBestFunctionEver = function(awesome, stuff){
return awesome + stuff;
}
and in foo.js I have this:
function init(){
var main = new Main(); // Shows that Main is undefined
var wrongVar = 6 + unInited // This should always give me an error
// Rest of init
}
JSHint works on per-file basis and doesn't 'see' variables defined in other files unless they are added to 'global' list. This can be done by either adding the corresponding comments ('/* global MY_LIB*/ - see http://www.jshint.com/docs/) in code, or by adding variables/functions you'd like to use globally to the 'Predefined' list in Preferences -> Javascript -> Code Quality Tool -> JSHint -> Predefined (,separated).
I include the statement:
"use strict";
at the beginning of most of my Javascript files.
JSLint has never before warned about this. But now it is, saying:
Use the function form of "use strict".
Does anyone know what the "function form" would be?
Include 'use strict'; as the first statement in a wrapping function, so it only affects that function. This prevents problems when concatenating scripts that aren't strict.
See Douglas Crockford's latest blog post Strict Mode Is Coming To Town.
Example from that post:
(function () {
'use strict';
// this function is strict...
}());
(function () {
// but this function is sloppy...
}());
Update:
In case you don't want to wrap in immediate function (e.g. it is a node module), then you can disable the warning.
For JSLint (per Zhami):
/*jslint node: true */
For JSHint:
/*jshint strict:false */
or (per Laith Shadeed)
/* jshint -W097 */
To disable any arbitrary warning from JSHint, check the map in JSHint source code (details in docs).
Update 2: JSHint supports node:boolean option. See .jshintrc at github.
/* jshint node: true */
If you're writing modules for NodeJS, they are already encapsulated. Tell JSLint that you've got node by including at the top of your file:
/*jslint node: true */
I'd suggest to use jshint instead.
It allows to suppress this warning via /*jshint globalstrict: true*/.
If you are writing a library, I would only suggest using global strict if your code is encapsulated into modules as is the case with nodejs.
Otherwise you'd force everyone who is using your library into strict mode.
I started creating a Node.js/browserify application following the Cross Platform JavaScript blog post. And I ran into this issue, because my brand new Gruntfile didn't pass jshint.
Luckily I found an answer in the Leanpub book on Grunt:
If we try it now, we will scan our Gruntfile… and get some errors:
$ grunt jshint
Running "jshint:all" (jshint) task
Linting Gruntfile.js...ERROR
[L1:C1] W097: Use the function form of "use strict".
'use strict';
Linting Gruntfile.js...ERROR
[L3:C1] W117: 'module' is not defined.
module.exports = function (grunt) {
Warning: Task "jshint:all" failed. Use --force to continue.
Both errors are because the Gruntfile is a Node program, and by default JSHint does not recognise or allow the use of module and the string version of use strict. We can set a JSHint rule that will accept our Node programs. Let’s edit our jshint task configuration and add an options key:
jshint: {
options: {
node: true
},
}
Adding node: true to the jshint options, to put jshint into "Node mode", removed both errors for me.
Add a file .jslintrc (or .jshintrc in the case of jshint) at the root of your project with the following content:
{
"node": true
}
There's nothing innately wrong with the string form.
Rather than avoid the "global" strict form for worry of concatenating non-strict javascript, it's probably better to just fix the damn non-strict javascript to be strict.
process.on('warning', function(e) {
'use strict';
console.warn(e.stack);
});
process.on('uncaughtException', function(e) {
'use strict';
console.warn(e.stack);
});
add this lines to at the starting point of your file
I think everyone missed the "suddenly" part of this question. Most likely, your .jshintrc has a syntax error, so it's not including the 'browser' line. Run it through a json validator to see where the error is.
This is how simple it is: If you want to be strict with all your code, add "use strict"; at the start of your JavaScript.
But if you only want to be strict with some of your code, use the function form. Anyhow, I would recomend you to use it at the beginning of your JavaScript because this will help you be a better coder.
I'm currently working on a small console project that depends a lot on the arguments that are passed initially and I'm looking for a good way to handle a configuration object in nodejs.
I have the project currently fully working with the following example but I think I'm relaying on the caching of modules when using 'require'.
lets assume a module options.js
'use strict';
var options = {
configName: '.jstail',
colorActive: (process.platform === 'win32') ? false : true, // deactivate color by default on windows platform
quiet: false,
debug: false,
config: null,
logFile: null,
setting: null
};
module.exports = options;
And my initial module init.js
#!/usr/bin/env node
'use strict';
var options = require('options'); // require above options module
// modify the options object based on args
I then have a logger that depends on this options
For example if quiet is set to true no logging should happen
logger.js
'use strict';
var options = require('options');
/**
* prints to console if not explicitly suppresed
* #param {String} text
*/
function log(text) {
if (!options.quiet) {
console.log('[LOG]: ' + text);
}
}
My big problem is (I think) that I'm relaying on the caching of nodejs modules when I require the options module in the logger
So my two questions are:
Am I right that this only works because of the caching of the modules that nodejs does for me?
Is there any better way to handle a dynamic global configuration?
I know there are several questions and tutorials around with a config file but thats not what I'm looking for.
Yes, this only works because of caching, though I wouldn't call it caching (but node.js docs do) rather than lazy initialization. It's ok to rely on that, a lot of modules do some initialization of first require, using it for configuration is also typical. Generally speaking, require is a node.js way of accessing global singleton objects.
The other way to do it is to load configuration from a single file, modify it and then pass it to other modules who need it, like this:
//index.js
var config = require('./config')
config.flag = false
var module1 = require('./module1')(config)
//module1.js
module.exports = function (config) {
// do stuff
}
It makes code more decoupled and testable but adds complexity. Difference between these two approaches is basically the same as using globals vs dependency injection. Use whatever you like.
Using RequireJS I'm building an app which make extensive use of widgets. For each widget I have at least 3 separate files:
request.js containing code for setting up request/response handlers to request a widget in another part of my application
controller.js containing handling between model and view
view.js containing handling between user and controller
Module definition in request.js:
define(['common/view/widget/entity/term/list/table/controller'],
function(WidgetController) { ... });
Module definition in controller.js:
define(['common/view/widget/entity/term/list/table/view'],
function(WidgetView) { ... });
Module definition of view.js is:
define(['module','require'],function(module,require) {
'use strict';
var WidgetView = <constructor definition>;
return WidgetView;
});
I have lots of these little situations as above in the case of widgets I have developed. What I dislike is using the full path every time when a module is requiring another module and both are located in the same folder. I'd like to simply specify as follows (assuming we have a RequireJS plugin which solves this for us):
define(['currentfolder!controller'],
function(WidgetController) { ... });
For this, I have written a small plugin, as I couldn't find it on the web:
define({
load: function (name, parentRequire, onload, config) {
var path = parentRequire.toUrl('.').substring(config.baseUrl.length) + '/' + name;
parentRequire([path], function (value) {
onload(value);
});
}
});
As you might notice, in its basic form it looks like the example of the RequireJS plugins documentation.
Now in some cases, the above works fine (e.g. from the request.js to the controller.js), but in other cases a load timeout occurs (from controller.js to view.js). When I look at the paths which are generated, all are proper RequireJS paths. Looking at the load timeouts, the following is logged:
Timestamp: 13-09-13 17:27:10
Error: Error: Load timeout for modules: currentfolder!view_unnormalized2,currentfolder!view
http://requirejs.org/docs/errors.html#timeout
Source File: http://localhost/app/vendor/requirejs/require.js?msv15z
Line: 159
The above log was from a test I did with only loading the view.js from controller.js using currentfolder!view in the list of modules in the define statement. Since I only requested currentfolder!view once, I'm confused as to why I both see currentfolder!view_unnormalized2 and currentfolder!view in the message.
Any idea as to why this might be happening?
My answer may not answer your primary questions, but it will help you achieve what you're trying to do with your plugin.
In fact, Require.js support relative paths for requiring modules when using CommonJS style. Like so:
define(function( require, exports, module ) {
var relativeModule = require("./subfolder/module");
module.exports = function() {
console.log( relativeModule );
};
});