Skip to content

Commit 62a2f92

Browse files
fiskersindresorhus
andauthored
Add no-this-assignment rule (#1018)
Co-authored-by: Sindre Sorhus <[email protected]>
1 parent 8606a13 commit 62a2f92

File tree

7 files changed

+179
-0
lines changed

7 files changed

+179
-0
lines changed

docs/rules/no-this-assignment.md

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
# Disallow assigning `this` to a variable
2+
3+
`this` should be used directly. If you want a reference to `this` from a higher scope, consider using [arrow function expression](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions) or [`Function#bind()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_objects/Function/bind).
4+
5+
## Fail
6+
7+
```js
8+
const foo = this;
9+
10+
setTimeout(function () {
11+
foo.bar();
12+
}, 1000);
13+
```
14+
15+
```js
16+
const foo = this;
17+
18+
class Bar {
19+
method() {
20+
foo.baz();
21+
}
22+
}
23+
24+
new Bar().method();
25+
```
26+
27+
## Pass
28+
29+
```js
30+
setTimeout(() => {
31+
this.bar();
32+
}, 1000);
33+
```
34+
35+
```js
36+
setTimeout(function () {
37+
this.bar();
38+
}.bind(this), 1000);
39+
```
40+
41+
```js
42+
class Bar {
43+
constructor(fooInstance) {
44+
this.fooInstance = fooInstance;
45+
}
46+
method() {
47+
this.fooInstance.baz();
48+
}
49+
}
50+
51+
new Bar(this).method();
52+
```

index.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ module.exports = {
7070
'unicorn/no-null': 'error',
7171
'unicorn/no-object-as-default-parameter': 'error',
7272
'unicorn/no-process-exit': 'error',
73+
'unicorn/no-this-assignment': 'error',
7374
'unicorn/no-unreadable-array-destructuring': 'error',
7475
'unicorn/no-unsafe-regex': 'off',
7576
'unicorn/no-unused-properties': 'off',

readme.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ Configure it in `package.json`.
6464
"unicorn/no-null": "error",
6565
"unicorn/no-object-as-default-parameter": "error",
6666
"unicorn/no-process-exit": "error",
67+
"unicorn/no-this-assignment": "error",
6768
"unicorn/no-unreadable-array-destructuring": "error",
6869
"unicorn/no-unsafe-regex": "off",
6970
"unicorn/no-unused-properties": "off",
@@ -140,6 +141,7 @@ Configure it in `package.json`.
140141
- [no-null](docs/rules/no-null.md) - Disallow the use of the `null` literal.
141142
- [no-object-as-default-parameter](docs/rules/no-object-as-default-parameter.md) - Disallow the use of objects as default parameters.
142143
- [no-process-exit](docs/rules/no-process-exit.md) - Disallow `process.exit()`.
144+
- [no-this-assignment](docs/rules/no-this-assignment.md) - Disallow assigning `this` to a variable.
143145
- [no-unreadable-array-destructuring](docs/rules/no-unreadable-array-destructuring.md) - Disallow unreadable array destructuring. *(partly fixable)*
144146
- [no-unsafe-regex](docs/rules/no-unsafe-regex.md) - Disallow unsafe regular expressions.
145147
- [no-unused-properties](docs/rules/no-unused-properties.md) - Disallow unused object properties.

rules/no-this-assignment.js

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
'use strict';
2+
const getDocumentationUrl = require('./utils/get-documentation-url');
3+
4+
const MESSAGE_ID = 'no-this-assignment';
5+
const messages = {
6+
[MESSAGE_ID]: 'Do not assign `this` to `{{name}}`.'
7+
};
8+
9+
const variableDeclaratorSelector = [
10+
'VariableDeclarator',
11+
'[init.type="ThisExpression"]',
12+
'[id.type="Identifier"]'
13+
].join('');
14+
15+
const assignmentExpressionSelector = [
16+
'AssignmentExpression',
17+
'[right.type="ThisExpression"]',
18+
'[left.type="Identifier"]'
19+
].join('');
20+
21+
const selector = `:matches(${variableDeclaratorSelector}, ${assignmentExpressionSelector})`;
22+
23+
const create = context => ({
24+
[selector](node) {
25+
const variable = node.type === 'AssignmentExpression' ? node.left : node.id;
26+
context.report({
27+
node,
28+
data: {name: variable.name},
29+
messageId: MESSAGE_ID
30+
});
31+
}
32+
});
33+
34+
module.exports = {
35+
create,
36+
meta: {
37+
type: 'suggestion',
38+
docs: {
39+
url: getDocumentationUrl(__filename)
40+
},
41+
messages
42+
}
43+
};

test/no-this-assignment.js

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
import {outdent} from 'outdent';
2+
import {test} from './utils/test.js';
3+
4+
test.visualize({
5+
valid: [
6+
'const {property} = this;',
7+
'const property = this.property;',
8+
'const [element] = this;',
9+
'const element = this[0];',
10+
'([element] = this);',
11+
'element = this[0];',
12+
'property = this.property;',
13+
'const [element] = [this];',
14+
'([element] = [this]);',
15+
'const {property} = {property: this};',
16+
'({property} = {property: this});',
17+
'const self = true && this;',
18+
'const self = false || this;',
19+
'const self = false ?? this;',
20+
'foo.bar = this;',
21+
'function foo(a = this) {}',
22+
'function foo({a = this}) {}',
23+
'function foo([a = this]) {}'
24+
],
25+
invalid: [
26+
'const foo = this;',
27+
'let foo;foo = this;',
28+
'var foo = bar, baz = this;'
29+
]
30+
});
31+
32+
test.babel({
33+
valid: [
34+
outdent`
35+
class A {
36+
foo = this;
37+
}
38+
`,
39+
outdent`
40+
class A {
41+
static foo = this;
42+
}
43+
`
44+
],
45+
invalid: []
46+
});
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
# Snapshot report for `test/no-this-assignment.js`
2+
3+
The actual snapshot is saved in `no-this-assignment.js.snap`.
4+
5+
Generated by [AVA](https://avajs.dev).
6+
7+
## Invalid #1
8+
1 | const foo = this;
9+
10+
> Error 1/1
11+
12+
`␊
13+
> 1 | const foo = this;␊
14+
| ^^^^^^^^^^ Do not assign `this` to `foo`.␊
15+
`
16+
17+
## Invalid #2
18+
1 | let foo;foo = this;
19+
20+
> Error 1/1
21+
22+
`␊
23+
> 1 | let foo;foo = this;␊
24+
| ^^^^^^^^^^ Do not assign `this` to `foo`.␊
25+
`
26+
27+
## Invalid #3
28+
1 | var foo = bar, baz = this;
29+
30+
> Error 1/1
31+
32+
`␊
33+
> 1 | var foo = bar, baz = this;␊
34+
| ^^^^^^^^^^ Do not assign `this` to `baz`.␊
35+
`
240 Bytes
Binary file not shown.

0 commit comments

Comments
 (0)