版本

no-invalid-this

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

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

规则详情

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

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

ECMAScript 模块中的顶级 `this` 始终被认为无效,因为其值为 `undefined`。

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

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

  • 函数的名称以大写字母开头。
  • 函数被分配给一个以大写字母开头的变量。
  • 函数是 ES2015 类别的构造函数。

此规则根据以下条件判断函数是否为方法

  • 函数位于对象文字上。
  • 函数被分配给一个属性。
  • 函数是 ES2015 类别的 method/getter/setter。

此规则允许以下函数中的 `this` 关键字

  • 函数的 `call/apply/bind` 方法被直接调用。
  • 如果提供了 `thisArg`,则该函数是数组方法(例如 `.forEach()`)的回调函数。
  • 函数在其 JSDoc 注释中具有 `@this` 标记。

此规则始终允许以下上下文中的 `this` 关键字

  • 在脚本的顶级。
  • 在类字段初始化器中。
  • 在类静态块中。

否则被视为问题。

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

此规则在严格模式下**不正确**代码的示例

在代码游乐场中打开
/*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);
});

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

在代码游乐场中打开
/*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;
}

选项

此规则具有一个对象选项,带有一个选项

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

capIsConstructor

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

如果您希望将这些函数视为“普通”函数,请将 `"capIsConstructor"` 设置为 `false`。

将 `"capIsConstructor"` 选项设置为 `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` 时,此规则**正确**代码的示例

在代码游乐场中打开
/*eslint no-invalid-this: ["error", { "capIsConstructor": false }]*/

"use strict";

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

何时不使用它

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

由 TypeScript 处理

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

请注意,从技术上讲,只有在启用了 `strict` 或 `noImplicitThis` 标志的情况下,TypeScript 才会捕获此问题。这些在大多数 TypeScript 项目中都是启用的,因为它们被认为是最佳实践。

版本

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

资源

更改语言