版本

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" 指令也处于严格模式。

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

在 Playground 中打开
/*eslint no-invalid-this: "error"*/

"use strict";

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

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

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

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

const 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);
});

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

在 Playground 中打开
/*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);
    }
}

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

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

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

const obj3 = 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);
    }
}

const bar = (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 的此规则,错误代码示例

在 Playground 中打开
/*eslint no-invalid-this: ["error", { "capIsConstructor": false }]*/

"use strict";

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

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

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

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

对于 "capIsConstructor" 选项设置为 false 的此规则,正确代码示例

在 Playground 中打开
/*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 的编译器会强制执行此检查。

请注意,从技术上讲,只有在启用 strictnoImplicitThis 标志时,TypeScript 才会捕获到这一点。这些在大多数 TypeScript 项目中都已启用,因为它们被认为是最佳实践。

版本

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

资源

更改语言