# no-invalid-this

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

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

# 规则详情

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

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

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

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

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

  • 函数名以大写开头。
  • 该函数被分配给以大写字母开头的变量。
  • 该函数是 ES2015 Classes 的构造函数。

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

  • 该函数位于对象字面上。
  • 该函数被分配给一个属性。
  • 该函数是 ES2015 类的方法/getter/setter。

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

  • 直接调用函数的call/apply/bind方法。
  • 如果给定 thisArg,则该函数是数组方法(例如 .forEach())的回调。
  • 该函数的 JSDoc 注释中有 @this 标记。

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

  • 在脚本的顶层。
  • 在类字段初始值设定项中。
  • 在类静态块中。

否则视为问题。

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

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

/*eslint no-invalid-this: "error"*/
/*eslint-env es6*/

"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"*/
/*eslint-env es6*/

"use strict";

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

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

class Foo {
    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 Foo {

    // 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,假设这些函数用作构造函数。

如果您希望将这些函数视为 'regular' 函数,请将 "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 关键字的通知,您可以安全地禁用此规则。

Last Updated: 5/13/2023, 8:55:38 PM