eslint-plugin-arrow-require-this
eslint-plugin-arrow-require-this copied to clipboard
DEPRECATED: ESLint rule to require arrow functions to reference the 'this' keyword
(DEPRECATED) ESLint Rule: arrow-require-this
DEPRECATION NOTICE: This project has been deprecated and merged into eslint-plugin-proper-arrows.
Overview
The arrow-require-this ESLint Rule requires => arrow functions to reference the this keyword. It also supports a "never" configuration, which means that => arrow functions should never use this.
The main purpose of this rule is to prevent usage of => arrow functions as just function shorthand (i.e., arr.map(x => x * 2)), which some argue is a misusage. The opinion follows that: the concise syntax (with all its myriad variations) can harm readability, so instead => arrow functions should only be used when the "lexical this" behavior is needed.
Since => arrow functions don't have their own this, they treat any this reference as a normal variable (not a special keyword). That means this is just lexically looked up through any parent scopes until a valid definition of this is found -- from a normal non-arrow function, or finally in the global scope itself.
Such this behavior is referred to as "lexical this", and it is one of the main design characteristics for => arrow functions.
For example:
var o = {
id: 42,
getData() {
ajax("https://some.tld/api",() => console.log(this.id));
}
};
o.getData(); // 42
In this snippet, the => arrow function is inside a normal function and therefore looks up and adopts its this (aka, "lexical this") -- which is set to the o object by the o.getData() call. Therefore, the arrow-require-this rule would not report an error.
By contrast, the arrow-require-this rule would report an error for:
var o = {
id: 42,
getData() {
ajax("https://some.tld/api",() => console.log(o.id));
}
};
o.getData(); // 42
Here, the => arrow function is lexically closed over the o rather than using "lexical this", so it can be considered a misusage of the => arrow function merely for shorthand; rather, the callback should have just been a regular named function expression (ie, function onResp(){ console.log(o.id); }).
To pass the arrow-require-this rule without a reported error, all => arrow functions must reference a this somewhere in their concise expression body or full { .. } function body (or in its nested => arrow functions when using "nested" configuration).
Enabling The Plugin
To use arrow-require-this, load it as a plugin into ESLint and configure the rule as desired.
.eslintrc.json
To load the plugin and enable its rule via a local or global .eslintrc.json configuration file:
"plugins": [
"@getify/arrow-require-this"
],
"rules": {
"@getify/arrow-require-this/all": "error"
}
package.json
To load the plugin and enable its rule via a project's package.json:
"eslintConfig": {
"plugins": [
"@getify/arrow-require-this"
],
"rules": {
"@getify/arrow-require-this/all": "error"
}
}
ESLint CLI parameters
To load the plugin and enable its rule via ESLint CLI parameters, use --plugin and --rule:
eslint .. --plugin='@getify/arrow-require-this' --rule='@getify/arrow-require-this/all: error' ..
eslint .. --plugin='@getify/arrow-require-this' --rule='@getify/arrow-require-this/all: [error,always]' ..
ESLint Node API
To use this plugin in Node.js with the ESLint API, require the npm module, and then (for example) pass the rule's definition to Linter#defineRule(..), similar to:
var arrowRequireThis = require("@getify/eslint-plugin-arrow-require-this");
// ..
var eslinter = new (require("eslint").Linter)();
eslinter.defineRule("@getify/arrow-require-this/all",arrowRequireThis.rules.all);
Then lint some code like this:
eslinter.verify(".. some code ..",{
rules: {
"@getify/arrow-require-this/all": ["error","always"]
}
});
Inline Comments
Once the plugin is loaded, the rule can be configured using inline code comments if desired, such as:
/* eslint "@getify/arrow-require-this/all": "error" */
/* eslint "@getify/arrow-require-this/all": ["error","always"] */
Rule Configuration
The arrow-require-this rule can be configured in three modes: "nested" (default), "always", and "never".
"nested" (default) permits a this to appear lower in a nested => arrow function (i.e., x = y => z => this.foo(z)), as long as there is no non-arrow function boundary crossed.
"always" is more strict, requiring every single => arrow function to have its own this reference.
"never" is the reverse, which is that all => arrow functions are forbidden from using this.
Configuration: "nested"
To configure this rule mode (default):
"@getify/arrow-require-this/all": "error"
"@getify/arrow-require-this/all": [ "error", "nested" ]
This rule mode allows a this to appear either in the => arrow function, or nested in a chain of => arrow functions, as long as there is no non-arrow function boundary crossed in between.
These => arrow functions will all pass the rule:
var a = b => this.foo(b);
var c = d => e => this.foo(e);
var f = (g = h => this.foo(h)) => g;
These => arrow functions will each fail the rule:
var a = b => foo(b);
var c = d => this.foo(e => e);
var f = (g = h => h) => this.foo(g);
var h = i => function(){ return j => this.foo(j); };
Configuration: "always"
To configure this rule mode:
"@getify/arrow-require-this/all": [ "error", "always" ]
This rule mode requires a this reference to appear in every single => arrow function (e.g., nested this is not sufficient).
These => arrow functions will all pass the rule:
var a = b => this.foo(b);
var c = d => this.foo(e => this.bar(e));
var f = (g = h => this.foo(h)) => this.bar(g);
These => arrow functions will each fail the rule:
var a = b => foo(b);
var c = d => e => this.foo(e);
var f = g => this.foo(h => h);
var i = (j = k => k) => this.foo(j);
Note: In each of the above examples, at least one of the => arrow functions does not have its own this, hence the mode's rule failure (which doesn't consider nested this).
Configuration: "never"
To configure this rule mode:
"@getify/arrow-require-this/all": [ "error", "never" ]
This rule mode forbids a this reference from appearing in any => arrow function.
These => arrow functions will all pass the rule:
var a = b => foo(b);
var c = d => foo(e => bar(e));
var f = (g = h => foo(h)) => bar(g);
These => arrow functions will each fail the rule:
var a = b => this.foo(b);
var c = d => e => this.foo(e);
var f = g => foo(h => this.bar(h));
npm Package
To use this plugin with a global install of ESLint (recommended):
npm install -g @getify/eslint-plugin-arrow-require-this
To use this plugin with a local install of ESLint:
npm install @getify/eslint-plugin-arrow-require-this
Builds
If you need to bundle/distribute this eslint plugin, use dist/arrow-require-this.js, which comes pre-built with the npm package distribution; you shouldn't need to rebuild it under normal circumstances.
However, if you download this repository via Git:
-
The included build utility (
scripts/build-core.js) builds (and minifies)dist/arrow-require-this.jsfrom source. -
To install the build and test dependencies, run
npm installfrom the project root directory. -
To manually run the build utility with npm:
npm run build -
To run the build utility directly without npm:
node scripts/build-core.js
Tests
A comprehensive test suite is included in this repository, as well as the npm package distribution. The default test behavior runs the test suite against lib/index.js.
-
The included Node.js test utility (
scripts/node-tests.js) runs the test suite. -
Ensure the test dependencies are installed by running
npm installfrom the project root directory.- Note: Starting with npm v5, the test utility is not run automatically during this
npm install. With npm v4 and before, the test utility automatically runs at this point.
- Note: Starting with npm v5, the test utility is not run automatically during this
-
To run the test utility with npm:
npm testOther npm test scripts:
-
npm run test:distwill run the test suite againstdist/arrow-require-this.jsinstead of the default oflib/index.js. -
npm run test:packagewill run the test suite as if the package had just been installed via npm. This ensurespackage.json:mainproperly referencesdist/arrow-require-this.jsfor inclusion. -
npm run test:allwill run all three modes of the test suite.
-
-
To run the test utility directly without npm:
node scripts/node-tests.js
Test Coverage
If you have Istanbul already installed on your system (requires v1.0+), you can use it to check the test coverage:
npm run coverage
Then open up coverage/lcov-report/index.html in a browser to view the report.
To run Istanbul directly without npm:
istanbul cover scripts/node-tests.js
Note: The npm script coverage:report is only intended for use by project maintainers; it sends coverage reports to Coveralls.
License
All code and documentation are (c) 2019 Kyle Simpson and released under the MIT License. A copy of the MIT License is also included.