Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Cleanup.

  • Loading branch information...
commit 6735394d4d940a57e87caa0894fae75d93ba3f31 1 parent 00d8d1f
Douglas Crockford authored
Showing with 159 additions and 167 deletions.
  1. +146 −152 fulljslint.js
  2. +13 −15 lint.html
298 fulljslint.js
View
@@ -38,9 +38,9 @@ SOFTWARE.
The second parameter is an optional object of options which control the
operation of JSLINT. Most of the options are booleans: They are all are
optional and have a default value of false. One of the options, predef,
- can be an array of names, which will be used to declare constant globals,
+ can be an array of names, which will be used to declare global variables,
or an object whose keys are used as global names, with a boolean value
- that determines if they are constant.
+ that determines if they are assignable.
If it checks out, JSLINT returns true. Otherwise, it returns false.
@@ -259,51 +259,13 @@ SOFTWARE.
*/
// We build the application inside a function so that we produce only a single
-// global variable. The function will be invoked, its return value is the JSLINT
-// application itself.
+// global variable. That function will be invoked immediately, and its return
+// value is the JSLINT function itself.
"use strict";
var JSLINT = (function () {
- function F() {} // Used by Object.create
-
- function is_own(object, name) {
-
-// The object.hasOwnProperty method fails when the property under consideration
-// is named 'hasOwnProperty'. So we have to use this more convoluted form.
-
- return Object.prototype.hasOwnProperty.call(object, name);
- }
-
-// Provide critical ES5 functions to ES3.
-
- if (typeof Array.isArray !== 'function') {
- Array.isArray = function (o) {
- return Object.prototype.toString.apply(o) === '[object Array]';
- };
- }
-
- if (typeof Object.create !== 'function') {
- Object.create = function (o) {
- F.prototype = o;
- return new F();
- };
- }
-
- if (typeof Object.keys !== 'function') {
- Object.keys = function (o) {
- var a = [], k;
- for (k in o) {
- if (is_own(o, k)) {
- a.push(k);
- }
- }
- return a;
- };
- }
-
-
var adsafe_id, // The widget's ADsafe id.
adsafe_may, // The widget may load approved scripts.
adsafe_went, // ADSAFE.go has been called.
@@ -328,7 +290,7 @@ var JSLINT = (function () {
'%': true
},
-// These are members that should not be permitted in the safe subset.
+// These are property names that should not be permitted in the safe subset.
banned = { // the member names that ADsafe prohibits.
'arguments' : true,
@@ -966,7 +928,7 @@ var JSLINT = (function () {
xmode,
xquote,
-// Regular expressions. Some of these are ridiculously long.
+// Regular expressions. Some of these are stupidly long.
// unsafe comment or string
ax = /@cc|<\/?|script|\]\s*\]|<\s*!|&lt/i,
@@ -1005,42 +967,78 @@ var JSLINT = (function () {
};
+ function F() {} // Used by Object.create
- function combine(t, o) {
- var n;
- for (n in o) {
- if (is_own(o, n)) {
- t[n] = o[n];
- }
- }
+ function is_own(object, name) {
+
+// The object.hasOwnProperty method fails when the property under consideration
+// is named 'hasOwnProperty'. So we have to use this more convoluted form.
+
+ return Object.prototype.hasOwnProperty.call(object, name);
}
- String.prototype.entityify = function () {
- return this
- .replace(/&/g, '&amp;')
- .replace(/</g, '&lt;')
- .replace(/>/g, '&gt;');
- };
+// Provide critical ES5 functions to ES3.
- String.prototype.isAlpha = function () {
- return (this >= 'a' && this <= 'z\uffff') ||
- (this >= 'A' && this <= 'Z\uffff');
- };
+ if (typeof Array.isArray !== 'function') {
+ Array.isArray = function (o) {
+ return Object.prototype.toString.apply(o) === '[object Array]';
+ };
+ }
+ if (typeof Object.create !== 'function') {
+ Object.create = function (o) {
+ F.prototype = o;
+ return new F();
+ };
+ }
- String.prototype.isDigit = function () {
- return (this >= '0' && this <= '9');
- };
+ if (typeof Object.keys !== 'function') {
+ Object.keys = function (o) {
+ var a = [], k;
+ for (k in o) {
+ if (is_own(o, k)) {
+ a.push(k);
+ }
+ }
+ return a;
+ };
+ }
+// Non standard methods
- String.prototype.supplant = function (o) {
- return this.replace(/\{([^{}]*)\}/g, function (a, b) {
- var r = o[b];
- return typeof r === 'string' || typeof r === 'number' ? r : a;
- });
- };
+ if (typeof String.prototype.entityify !== 'function') {
+ String.prototype.entityify = function () {
+ return this
+ .replace(/&/g, '&amp;')
+ .replace(/</g, '&lt;')
+ .replace(/>/g, '&gt;');
+ };
+ }
+
+ if (typeof String.prototype.isAlpha !== 'function') {
+ String.prototype.isAlpha = function () {
+ return (this >= 'a' && this <= 'z\uffff') ||
+ (this >= 'A' && this <= 'Z\uffff');
+ };
+ }
+
+ if (typeof String.prototype.isDigit !== 'function') {
+ String.prototype.isDigit = function () {
+ return (this >= '0' && this <= '9');
+ };
+ }
- String.prototype.name = function () {
+ if (typeof String.prototype.supplant !== 'function') {
+ String.prototype.supplant = function (o) {
+ return this.replace(/\{([^{}]*)\}/g, function (a, b) {
+ var r = o[b];
+ return typeof r === 'string' || typeof r === 'number' ? r : a;
+ });
+ };
+ }
+
+ if (typeof String.prototype.name !== 'function') {
+ String.prototype.name = function () {
// If the string looks like an identifier, then we can return it as is.
// If the string contains no control characters, no quote characters, and no
@@ -1048,22 +1046,32 @@ var JSLINT = (function () {
// Otherwise we must also replace the offending characters with safe
// sequences.
- if (ix.test(this)) {
- return this;
- }
- if (nx.test(this)) {
- return '"' + this.replace(nxg, function (a) {
- var c = escapes[a];
- if (c) {
- return c;
- }
- return '\\u' + ('0000' + a.charCodeAt().toString(16)).slice(-4);
- }) + '"';
- }
- return '"' + this + '"';
- };
+ if (ix.test(this)) {
+ return this;
+ }
+ if (nx.test(this)) {
+ return '"' + this.replace(nxg, function (a) {
+ var c = escapes[a];
+ if (c) {
+ return c;
+ }
+ return '\\u' + ('0000' + a.charCodeAt().toString(16)).slice(-4);
+ }) + '"';
+ }
+ return '"' + this + '"';
+ };
+ }
+ function combine(t, o) {
+ var n;
+ for (n in o) {
+ if (is_own(o, n)) {
+ t[n] = o[n];
+ }
+ }
+ }
+
function assume() {
if (!option.safe) {
if (option.rhino) {
@@ -1149,7 +1157,7 @@ var JSLINT = (function () {
-// lexical analysis
+// lexical analysis and token construction
var lex = (function lex() {
var character, from, line, s;
@@ -1422,21 +1430,6 @@ var JSLINT = (function () {
}
}
}
-// t = match(rx[xmode] || tx);
-// if (!t) {
-// if (xmode === 'html') {
-// return it('(error)', s.charAt(0));
-// } else {
-// t = '';
-// c = '';
-// while (s && s < '!') {
-// s = s.substr(1);
-// }
-// if (s) {
-// errorAt("Unexpected '{a}'.",
-// line, character, s.substr(0, 1));
-// }
-// }
t = match(rx[xmode] || tx);
if (!t) {
t = '';
@@ -1487,8 +1480,7 @@ var JSLINT = (function () {
}
if (t.substr(t.length - 1) === '.') {
warningAt(
- "A trailing decimal point can be confused with a dot '{a}'.",
- line, character, t);
+"A trailing decimal point can be confused with a dot '{a}'.", line, character, t);
}
return it('(number)', t);
}
@@ -1961,6 +1953,7 @@ klass: do {
obj = predefined;
break;
default:
+ error("What?");
}
t = lex.token();
loop: for (;;) {
@@ -2111,10 +2104,10 @@ loop: for (;;) {
// This is the heart of JSLINT, the Pratt parser. In addition to parsing, it
-// is looking for ad hoc lint patterns. We add to Pratt's model .fud, which is
-// like nud except that it is only used on the first token of a statement.
-// Having .fud makes it much easier to define JavaScript. I retained Pratt's
-// nomenclature.
+// is looking for ad hoc lint patterns. We add .fud to Pratt's model, which is
+// like .nud except that it is only used on the first token of a statement.
+// Having .fud makes it much easier to define statement-oriented languages like
+// JavaScript. I retained Pratt's nomenclature.
// .nud Null denotation
// .fud First null denotation
@@ -2122,9 +2115,9 @@ loop: for (;;) {
// lbp Left binding power
// rbp Right binding power
-// They are key to the parsing method called Top Down Operator Precedence.
+// They are elements of the parsing method called Top Down Operator Precedence.
- function parse(rbp, initial) {
+ function expression(rbp, initial) {
var left;
if (nexttoken.id === '(end)') {
error("Unexpected early end of program.", token);
@@ -2199,7 +2192,6 @@ loop: for (;;) {
}
}
-
function nonadjacent(left, right) {
if (option.white) {
left = left || token;
@@ -2308,7 +2300,7 @@ loop: for (;;) {
var x = symbol(s, 150);
reserveName(x);
x.nud = (typeof f === 'function') ? f : function () {
- this.right = parse(150);
+ this.right = expression(150);
this.arity = 'unary';
if (this.id === '++' || this.id === '--') {
if (option.plusplus) {
@@ -2361,7 +2353,7 @@ loop: for (;;) {
return f(left, this);
} else {
this.left = left;
- this.right = parse(p);
+ this.right = expression(p);
return this;
}
};
@@ -2374,7 +2366,7 @@ loop: for (;;) {
x.led = function (left) {
nobreaknonadjacent(prevtoken, token);
nonadjacent(token, nexttoken);
- var right = parse(100);
+ var right = expression(100);
if ((left && left.id === 'NaN') || (right && right.id === 'NaN')) {
warning("Use the isNaN function to compare with NaN.", this);
} else if (f) {
@@ -2430,13 +2422,13 @@ loop: for (;;) {
if (!left.left || left.left.value === 'arguments') {
warning('Bad assignment.', that);
}
- that.right = parse(19);
+ that.right = expression(19);
return that;
} else if (left.identifier && !left.reserved) {
if (funct[left.value] === 'exception') {
warning("Do not assign to the exception parameter.", left);
}
- that.right = parse(19);
+ that.right = expression(19);
return that;
}
if (left === syntax['function']) {
@@ -2458,7 +2450,7 @@ loop: for (;;) {
warning("Unexpected use of '{a}'.", this, this.id);
}
this.left = left;
- this.right = parse(p);
+ this.right = expression(p);
return this;
};
return x;
@@ -2476,7 +2468,7 @@ loop: for (;;) {
if (left) {
if (left.id === '.' || left.id === '[' ||
(left.identifier && !left.reserved)) {
- parse(19);
+ expression(19);
return that;
}
if (left === syntax['function']) {
@@ -2594,7 +2586,7 @@ loop: for (;;) {
if (!noindent) {
indentation();
}
- r = parse(0, true);
+ r = expression(0, true);
// Look for the final semicolon.
@@ -2646,6 +2638,9 @@ loop: for (;;) {
if (option.adsafe) {
switch (begin) {
case 'script':
+
+// JSLint is also the static analizer for ADsafe. See www.ADsafe.org.
+
if (!adsafe_may) {
if (nexttoken.value !== 'ADSAFE' ||
peek(0).id !== '.' ||
@@ -2682,7 +2677,7 @@ loop: for (;;) {
advance('(');
advance('(string)');
comma();
- f = parse(0);
+ f = expression(0);
if (f.id !== 'function') {
error('The second argument to lib must be a function.', f);
}
@@ -2779,7 +2774,6 @@ loop: for (;;) {
// CSS parsing.
-
function cssName() {
if (nexttoken.identifier) {
advance();
@@ -4267,9 +4261,9 @@ loop: for (;;) {
bitwiseassignop('>>>=', 'assignshiftrightunsigned', 20);
infix('?', function (left, that) {
that.left = left;
- that.right = parse(10);
+ that.right = expression(10);
advance(':');
- that['else'] = parse(10);
+ that['else'] = expression(10);
return that;
}, 30);
@@ -4316,7 +4310,7 @@ loop: for (;;) {
infix('in', 'in', 120);
infix('instanceof', 'instanceof', 120);
infix('+', function (left, that) {
- var right = parse(130);
+ var right = expression(130);
if (left && right && left.id === '(string)' && right.id === '(string)') {
left.value += right.value;
left.character = right.character;
@@ -4332,28 +4326,28 @@ loop: for (;;) {
prefix('+', 'num');
prefix('+++', function () {
warning("Confusing pluses.");
- this.right = parse(150);
+ this.right = expression(150);
this.arity = 'unary';
return this;
});
infix('+++', function (left) {
warning("Confusing pluses.");
this.left = left;
- this.right = parse(130);
+ this.right = expression(130);
return this;
}, 130);
infix('-', 'sub', 130);
prefix('-', 'neg');
prefix('---', function () {
warning("Confusing minuses.");
- this.right = parse(150);
+ this.right = expression(150);
this.arity = 'unary';
return this;
});
infix('---', function (left) {
warning("Confusing minuses.");
this.left = left;
- this.right = parse(130);
+ this.right = expression(130);
return this;
}, 130);
infix('*', 'mult', 140);
@@ -4368,7 +4362,7 @@ loop: for (;;) {
prefix('--', 'predec');
syntax['--'].exps = true;
prefix('delete', function () {
- var p = parse(0);
+ var p = expression(0);
if (!p || (p.id !== '.' && p.id !== '[')) {
warning("Variables should not be deleted.");
}
@@ -4381,11 +4375,11 @@ loop: for (;;) {
if (option.bitwise) {
warning("Unexpected '{a}'.", this, '~');
}
- parse(150);
+ expression(150);
return this;
});
prefix('!', function () {
- this.right = parse(150);
+ this.right = expression(150);
this.arity = 'unary';
if (bang[this.right.id] === true) {
warning("Confusing use of '{a}'.", this, '!');
@@ -4394,7 +4388,7 @@ loop: for (;;) {
});
prefix('typeof', 'typeof');
prefix('new', function () {
- var c = parse(155), i;
+ var c = expression(155), i;
if (c && c.id !== 'function') {
if (c.identifier) {
c['new'] = true;
@@ -4558,7 +4552,7 @@ loop: for (;;) {
}
if (nexttoken.id !== ')') {
for (;;) {
- p[p.length] = parse(10);
+ p[p.length] = expression(10);
n += 1;
if (nexttoken.id !== ',') {
break;
@@ -4598,7 +4592,7 @@ loop: for (;;) {
if (nexttoken.id === 'function') {
nexttoken.immed = true;
}
- var v = parse(0);
+ var v = expression(0);
advance(')', this);
nospace(prevtoken, token);
if (option.immed && v.id === 'function') {
@@ -4617,7 +4611,7 @@ loop: for (;;) {
infix('[', function (left, that) {
nobreak(prevtoken, token);
nospace();
- var e = parse(0), s;
+ var e = expression(0), s;
if (e && e.type === '(string)') {
if (option.safe && banned[e.value] === true) {
warning("ADsafe restricted word '{a}'.", that, e.value);
@@ -4668,7 +4662,7 @@ loop: for (;;) {
if (b && token.line !== nexttoken.line) {
indentation();
}
- this.first.push(parse(10));
+ this.first.push(expression(10));
if (nexttoken.id === ',') {
comma();
if (nexttoken.id === ']' && !option.es5) {
@@ -4819,7 +4813,7 @@ loop: for (;;) {
}
advance(':');
nonadjacent(token, nexttoken);
- parse(10);
+ expression(10);
}
if (seen[i] === true) {
warning("Duplicate member '{a}'.", nexttoken, i);
@@ -4886,7 +4880,7 @@ loop: for (;;) {
error("Variable {a} was not declared correctly.",
nexttoken, nexttoken.value);
}
- value = parse(0);
+ value = expression(0);
name.first = value;
}
if (nexttoken.id !== ',') {
@@ -4937,11 +4931,11 @@ loop: for (;;) {
advance('(');
nonadjacent(this, t);
nospace();
- parse(20);
+ expression(20);
if (nexttoken.id === '=') {
warning("Expected a conditional expression and instead saw an assignment.");
advance('=');
- parse(20);
+ expression(20);
}
advance(')', t);
nospace(prevtoken, token);
@@ -5001,11 +4995,11 @@ loop: for (;;) {
advance('(');
nonadjacent(this, t);
nospace();
- parse(20);
+ expression(20);
if (nexttoken.id === '=') {
warning("Expected a conditional expression and instead saw an assignment.");
advance('=');
- parse(20);
+ expression(20);
}
advance(')', t);
nospace(prevtoken, token);
@@ -5024,7 +5018,7 @@ loop: for (;;) {
advance('(');
nonadjacent(this, t);
nospace();
- this.condition = parse(20);
+ this.condition = expression(20);
advance(')', t);
nospace(prevtoken, token);
nonadjacent(token, nexttoken);
@@ -5051,7 +5045,7 @@ loop: for (;;) {
}
indentation(-option.indent);
advance('case');
- this.cases.push(parse(20));
+ this.cases.push(expression(20));
g = true;
advance(':');
funct['(verb)'] = 'case';
@@ -5124,11 +5118,11 @@ loop: for (;;) {
nonadjacent(token, t);
advance('(');
nospace();
- parse(20);
+ expression(20);
if (nexttoken.id === '=') {
warning("Expected a conditional expression and instead saw an assignment.");
advance('=');
- parse(20);
+ expression(20);
}
advance(')', t);
nospace(prevtoken, token);
@@ -5165,7 +5159,7 @@ loop: for (;;) {
advance();
}
advance('in');
- parse(20);
+ expression(20);
advance(')', t);
s = block(true);
if (!f && (s.length > 1 || typeof s[0] !== 'object' ||
@@ -5182,7 +5176,7 @@ loop: for (;;) {
varstatement();
} else {
for (;;) {
- parse(0, 'for');
+ expression(0, 'for');
if (nexttoken.id !== ',') {
break;
}
@@ -5193,11 +5187,11 @@ loop: for (;;) {
nolinebreak(token);
advance(';');
if (nexttoken.id !== ';') {
- parse(20);
+ expression(20);
if (nexttoken.id === '=') {
warning("Expected a conditional expression and instead saw an assignment.");
advance('=');
- parse(20);
+ expression(20);
}
}
nolinebreak(token);
@@ -5208,7 +5202,7 @@ loop: for (;;) {
}
if (nexttoken.id !== ')') {
for (;;) {
- parse(0, 'for');
+ expression(0, 'for');
if (nexttoken.id !== ',') {
break;
}
@@ -5278,7 +5272,7 @@ loop: for (;;) {
}
if (nexttoken.id !== ';' && !nexttoken.reach) {
nonadjacent(token, nexttoken);
- this.first = parse(20);
+ this.first = expression(20);
}
reachable('return');
return this;
@@ -5288,7 +5282,7 @@ loop: for (;;) {
stmt('throw', function () {
nolinebreak(this);
nonadjacent(token, nexttoken);
- this.first = parse(20);
+ this.first = expression(20);
reachable('throw');
return this;
}).exps = true;
28 lint.html
View
@@ -64,8 +64,7 @@ <h2 id=what>What is <code>JSLint</code>?</h2>
language. It was originally intended to do small tasks in webpages, tasks
for which Java was too heavy and clumsy. But JavaScript is a very capable
language, and it is now being used in larger projects. Many of the features
- that were intended to make the language easy to use are troublesome for
- larger projects. A <code>lint</code> for JavaScript is needed: <a href="http://www.JSLint.com/"><code>JSLint</code></a>,
+ that were intended to make the language easy to use are troublesome when projects become complicated. A <code>lint</code> for JavaScript is needed: <a href="http://www.JSLint.com/"><code>JSLint</code></a>,
a JavaScript syntax checker and validator.</p>
<p><code>JSLint</code> takes a JavaScript source and scans it. If it finds
@@ -82,8 +81,8 @@ <h2 id=what>What is <code>JSLint</code>?</h2>
Conventions for the JavaScript Programming Language</i></a>. </p>
<p>JavaScript is a sloppy language, but inside it there is an elegant, better
language. <code>JSLint</code> helps you to program in that better language
- and to avoid most of the slop.</p>
-<p><code>JSLint</code> can operate on JavaScript source, HTML source, or <a href="http://www.JSON.org/">JSON</a>
+ and to avoid most of the slop. JSLint will reject programs that browsers will accept because JSLint is concerned with the quality of your code and browsers are not. You should accept all of JSLint's advice.</p>
+<p><code>JSLint</code> can operate on JavaScript source, HTML source, CSS source, or <a href="http://www.JSON.org/">JSON</a>
text.</p>
<h2 id=global>Global Variables</h2>
<p>JavaScript's <a href="http://yuiblog.com/blog/2006/06/01/global-domination/">biggest
@@ -103,7 +102,7 @@ <h2 id=global>Global Variables</h2>
<p>The declaration should appears near the top of the file. It must appear before the use of the variables
it declares. </p>
<p>It is necessary to use a <code>var</code> statement to declare a variable before that variable is assigned to. </p>
-<p><code>JSLint</code> also recognizes a <code>/*global */</code> comment that can indicate to <code>JSLint</code> that variables used in this file were defined in other files. The comment can contain a comma separated list of names. Each name can optionally be followed by a colon and either <code>true</code> or <code>false</code>, <code>true</code> indicated that the variable may be assigned to by this file, and <code>false</code> indicating that assignment is not allowed which is the default.</p>
+<p><code>JSLint</code> also recognizes a <code>/*global */</code> comment that can indicate to <code>JSLint</code> that variables used in this file were defined in other files. The comment can contain a comma separated list of names. Each name can optionally be followed by a colon and either <code>true</code> or <code>false</code>, <code>true</code> indicated that the variable may be assigned to by this file, and <code>false</code> indicating that assignment is not allowed (which is the default).</p>
<p id=browser>Some globals can be predefined for you. Select the <i>Assume
a browser</i> (<code>browser</code>) <a href="#options">option</a> to
predefine the standard global properties that are supplied by web browsers,
@@ -113,7 +112,7 @@ <h2 id=global>Global Variables</h2>
<code>/*global addEventListener: false, blur: false, clearInterval: false, clearTimeout: false, close: false, closed: false, defaultStatus: false, document: false, event: false, focus: false, frames: false, getComputedStyle: false, history: false, Image: false, length: false, location: false, moveBy: false, moveTo: false, name: false, navigator: false, onblur: true, onerror: true, onfocus: true, onload: true, onresize: true, onunload: true, open: false, opener: false, Option: false, parent: false, print: false, resizeBy: false, resizeTo: false, screen: false, scroll: false, scrollBy: false, scrollTo: false, setInterval: false, setTimeout: false, status: false, top: false, XMLHttpRequest: false */</code></blockquote>
<p> The <code>browser</code> <a href="#options">option</a> does
not include the aliases of the global object, <code>window</code> and
- <code>self</code>. </p>
+ <code>self</code> because the potential for misuse is so great.</p>
<p id=devel>Select the
<label for="JSLINT_DEVEL" title="devel"><em>Assume console, alert, ...</em></label>
(<code>devel</code>) <a href="#options">option</a> to predefine globals that are useful in development but that should be avoided in production, such as <code>console</code> and <code>alert</code>. It has the same
@@ -137,9 +136,9 @@ <h2 id=global>Global Variables</h2>
<p><code>/*global ActiveXObject: false, CScript: false, Debug: false, Enumerator: false, System: false, VBArray: false, WScript: false */</code></p>
</blockquote>
<h2 id=semicolon>Semicolon</h2>
-<p>JavaScript uses a C-like syntax which requires the use of semicolons to delimit
- statements. JavaScript attempts to make semicolons optional with a semicolon
- insertion mechanism. This is dangerous.</p>
+<p>JavaScript uses a C-like syntax which requires the use of semicolons to delimit certain
+ statements. JavaScript attempts to make those semicolons optional with a semicolon
+ insertion mechanism. This is dangerous because it can mask errors.</p>
<p>Like C, JavaScript has <code>++</code> and <code>--</code> and <code>(</code> operators
which can be prefixes or suffixes. The disambiguation is done by the semicolon.</p>
<p>In JavaScript, a linefeed can be whitespace or it can act as a semicolon.
@@ -149,7 +148,7 @@ <h2 id=semicolon>Semicolon</h2>
<code>while</code>. <code>JSLint</code> does not expect to see unnecessary semicolons or the
empty statement.</p>
<h2 id=breaking>Line Breaking</h2>
-<p>As a further defense against the semicolon insertion mechanism, <code>JSLint</code>
+<p>As a further defense against the semicolon insertion mechanism and editing mishaps, <code>JSLint</code>
expects long statements to be broken only after one of these punctuation
characters or operators:</p>
<p align="center"><code>, ; : { } ( [ = &lt; &gt; ? ! + - * / % ~ ^ | &amp; </code></p>
@@ -163,7 +162,7 @@ <h2 id=breaking>Line Breaking</h2>
<p><code>JSLint</code> allows you to turn on the <i>Tolerate sloppy line
breaking</i> (<code>laxbreak</code>) <a href="#options">option</a>. </p>
<p>Semicolon insertion can mask copy/paste errors. If you always break lines
- after infix operators, then <code>JSLint</code> can do better at finding errors.</p>
+ after infix operators, then <code>JSLint</code> can do better at finding other errors.</p>
<h2 id=comma>Comma</h2>
<p>The comma operator can lead to excessively tricky expressions. It can also
mask some programming errors.</p>
@@ -223,7 +222,7 @@ <h2 id=forin><code>for</code> <code>in</code></h2>
the names of all of the properties of an object. <a href="http://yuiblog.com/blog/2006/09/26/for-in-intrigue/">Unfortunately,
it also loops through all of the members which were inherited through
the prototype chain.</a> This has the bad side effect of serving up method
- functions when the interest is in data members.</p>
+ functions when the interest is in data members. If a program is written without awareness of this situation, then it can fail.</p>
<p>The body of every <code>for</code> <code>in</code> statement should be
wrapped in an <code>if</code> statement that does filtering. It can select
for a particular type or range of values, or it can exclude functions,
@@ -402,7 +401,7 @@ <h2 id=not>Not Looked For</h2>
<p><code>JSLint</code> does not do flow analysis to determine that variables are assigned
values before used. This is because variables are given a value (<code>undefined</code>)
- which is a reasonable default for many applications.</p>
+ that is a reasonable default for many applications.</p>
<p><code>JSLint</code> does not do any kind of global analysis. It does
not attempt to determine that functions used with <code>new</code> are
@@ -602,8 +601,7 @@ <h2 id=options>Options</h2>
<tr>
<td>Predefined <small>( , separated)</small></td>
<td><code>predef</code></td>
- <td>An array of strings, the names of predefined global variables, or an object whose keys are global variable names, and whose values are booleans that determine if each variable is constant.
- <code>predef</code> is used with the <code>option</code> object, but not
+ <td>An array of strings, the names of predefined global variables, or an object whose keys are global variable names, and whose values are booleans that determine if each variable is assignable (also see <a href="#global">global</a>). <code>predef</code> is used with the <code>option</code> object, but not
with the <code>/*jslint */</code> comment. You can also use the <code>var</code>
statement to declare global variables in a script file.</td>
</tr>
Please sign in to comment.
Something went wrong with that request. Please try again.