no-invalid-this

禁止在 this 的值为 undefined 的上下文中使用 this

在严格模式下,类或类对象之外的 this 关键字可能是 undefined 并引发 TypeError

¥Under the strict mode, this keywords outside of classes or class-like objects might be undefined and raise a TypeError.

规则详情

¥Rule Details

此规则旨在标记在 this 的值为 undefined 的上下文中使用 this 关键字。

¥This rule aims to flag usage of this keywords in contexts where the value of this is undefined.

脚本中的顶层 this 始终被认为是有效的,因为无论严格模式如何,它都引用全局对象。

¥Top-level this in scripts is always considered valid because it refers to the global object regardless of the strict mode.

ECMAScript 模块中的顶层 this 总是被认为是无效的,因为它的值是 undefined

¥Top-level this in ECMAScript modules is always considered invalid because its value is undefined.

对于 this 内部函数,这个规则基本上是检查包含 this 关键字的函数是构造函数还是方法。请注意,箭头函数具有词法 this,因此该规则检查它们的封闭上下文。

¥For this inside functions, this rule basically checks whether or not the function containing this keyword is a constructor or a method. Note that arrow functions have lexical this, and that therefore this rule checks their enclosing contexts.

该规则根据以下条件判断函数是否为构造函数:

¥This rule judges from following conditions whether or not the function is a constructor:

  • 函数名以大写开头。

    ¥The name of the function starts with uppercase.

  • 该函数被分配给以大写字母开头的变量。

    ¥The function is assigned to a variable which starts with an uppercase letter.

  • 该函数是 ES2015 Classes 的构造函数。

    ¥The function is a constructor of ES2015 Classes.

该规则从以下条件判断函数是否为方法:

¥This rule judges from following conditions whether or not the function is a method:

  • 该函数位于对象字面上。

    ¥The function is on an object literal.

  • 该函数被分配给一个属性。

    ¥The function is assigned to a property.

  • 该函数是 ES2015 类的方法/getter/setter。

    ¥The function is a method/getter/setter of ES2015 Classes.

此规则允许在以下函数中使用 this 关键字:

¥And this rule allows this keywords in functions below:

  • 直接调用函数的 call/apply/bind 方法。

    ¥The call/apply/bind method of the function is called directly.

  • 如果给定 thisArg,则该函数是数组方法(例如 .forEach())的回调。

    ¥The function is a callback of array methods (such as .forEach()) if thisArg is given.

  • 该函数的 JSDoc 注释中有 @this 标记。

    ¥The function has @this tag in its JSDoc comment.

并且此规则始终允许在以下上下文中使用 this 关键字:

¥And this rule always allows this keywords in the following contexts:

  • 在脚本的顶层。

    ¥At the top level of scripts.

  • 在类字段初始值设定项中。

    ¥In class field initializers.

  • 在类静态块中。

    ¥In class static blocks.

否则视为问题。

¥Otherwise are considered problems.

该规则仅适用于严格模式。在 ESLint 配置中使用 "parserOptions": { "sourceType": "module" },即使没有 "use strict" 指令,你的代码也处于严格模式。

¥This rule applies only in strict mode. With "parserOptions": { "sourceType": "module" } in the ESLint configuration, your code is in strict mode even without a "use strict" directive.

严格模式下此规则的错误代码示例:

¥Examples of incorrect code for this rule in strict mode:

在线运行
/*eslint no-invalid-this: "error"*/

"use strict";

(function() {
    this.a = 0;
    baz(() => this);
})();

function foo() {
    this.a = 0;
    baz(() => this);
}

var foo = function() {
    this.a = 0;
    baz(() => this);
};

foo(function() {
    this.a = 0;
    baz(() => this);
});

var obj = {
    aaa: function() {
        return function foo() {
            // There is in a method `aaa`, but `foo` is not a method.
            this.a = 0;
            baz(() => this);
        };
    }
};

foo.forEach(function() {
    this.a = 0;
    baz(() => this);
});

严格模式下此规则的正确代码示例:

¥Examples of correct code for this rule in strict mode:

在线运行
/*eslint no-invalid-this: "error"*/

"use strict";

this.a = 0;
baz(() => this);

function Foo() {
    // OK, this is in a legacy style constructor.
    this.a = 0;
    baz(() => this);
}

class Bar {
    constructor() {
        // OK, this is in a constructor.
        this.a = 0;
        baz(() => this);
    }
}

var obj = {
    foo: function foo() {
        // OK, this is in a method (this function is on object literal).
        this.a = 0;
    }
};

var obj = {
    foo() {
        // OK, this is in a method (this function is on object literal).
        this.a = 0;
    }
};

var obj = {
    get foo() {
        // OK, this is in a method (this function is on object literal).
        return this.a;
    }
};

var obj = Object.create(null, {
    foo: {value: function foo() {
        // OK, this is in a method (this function is on object literal).
        this.a = 0;
    }}
});

Object.defineProperty(obj, "foo", {
    value: function foo() {
        // OK, this is in a method (this function is on object literal).
        this.a = 0;
    }
});

Object.defineProperties(obj, {
    foo: {value: function foo() {
        // OK, this is in a method (this function is on object literal).
        this.a = 0;
    }}
});

function Foo() {
    this.foo = function foo() {
        // OK, this is in a method (this function assigns to a property).
        this.a = 0;
        baz(() => this);
    };
}

obj.foo = function foo() {
    // OK, this is in a method (this function assigns to a property).
    this.a = 0;
};

Foo.prototype.foo = function foo() {
    // OK, this is in a method (this function assigns to a property).
    this.a = 0;
};

class Baz {

    // OK, this is in a class field initializer.
    a = this.b;

    // OK, static initializers also have valid this.
    static a = this.b;

    foo() {
        // OK, this is in a method.
        this.a = 0;
        baz(() => this);
    }

    static foo() {
        // OK, this is in a method (static methods also have valid this).
        this.a = 0;
        baz(() => this);
    }

    static {
        // OK, static blocks also have valid this.
        this.a = 0;
        baz(() => this);
    }
}

var foo = (function foo() {
    // OK, the `bind` method of this function is called directly.
    this.a = 0;
}).bind(obj);

foo.forEach(function() {
    // OK, `thisArg` of `.forEach()` is given.
    this.a = 0;
    baz(() => this);
}, thisArg);

/** @this Foo */
function foo() {
    // OK, this function has a `@this` tag in its JSDoc comment.
    this.a = 0;
}

选项

¥Options

此规则有一个对象选项,有一个选项:

¥This rule has an object option, with one option:

  • "capIsConstructor": false(默认 true)禁止假设名称以大写字母开头的函数是构造函数。

    ¥"capIsConstructor": false (default true) disables the assumption that a function which name starts with an uppercase is a constructor.

capIsConstructor

默认情况下,此规则始终允许在名称以大写字母开头的函数和分配给名称以大写字母开头的变量的匿名函数中使用 this,假设这些函数用作构造函数。

¥By default, this rule always allows the use of this in functions which name starts with an uppercase and anonymous functions that are assigned to a variable which name starts with an uppercase, assuming that those functions are used as constructor functions.

如果你希望将这些函数视为 ‘regular’ 函数,请将 "capIsConstructor" 设置为 false

¥Set "capIsConstructor" to false if you want those functions to be treated as ‘regular’ functions.

此规则的错误代码示例("capIsConstructor" 选项设置为 false):

¥Examples of incorrect code for this rule with "capIsConstructor" option set to false:

在线运行
/*eslint no-invalid-this: ["error", { "capIsConstructor": false }]*/

"use strict";

function Foo() {
    this.a = 0;
}

var bar = function Foo() {
    this.a = 0;
}

var Bar = function() {
    this.a = 0;
};

Baz = function() {
    this.a = 0;
};

此规则的正确代码示例("capIsConstructor" 选项设置为 false):

¥Examples of correct code for this rule with "capIsConstructor" option set to false:

在线运行
/*eslint no-invalid-this: ["error", { "capIsConstructor": false }]*/

"use strict";

obj.Foo = function Foo() {
    // OK, this is in a method.
    this.a = 0;
};

何时不使用

¥When Not To Use It

如果你不想收到有关在类或类对象之外使用 this 关键字的通知,你可以安全地禁用此规则。

¥If you don’t want to be notified about usage of this keyword outside of classes or class-like objects, you can safely disable this rule.

由 TypeScript 处理

使用 TypeScript 时禁用此规则是安全的,因为 TypeScript 的编译器强制执行此检查。

请注意,从技术上讲,只有启用了 strictnoImplicitThis 标志,TypeScript 才会捕获此问题。大多数 TypeScript 项目都启用了这些功能,因为它们被认为是最佳实践。

版本

此规则是在 ESLint v1.0.0-rc-2 中引入。

资源

ESLint 中文网
粤ICP备13048890号