版本

no-invalid-this

禁止在 this 的值為 undefined 的情況下使用 this

在嚴格模式下,類別或類別物件之外的 this 關鍵字可能是 undefined 並引發 TypeError

規則詳情

此規則旨在標記 this 關鍵字在 this 的值為 undefined 的情況下的使用。

腳本中的頂層 this 始終被認為是有效的,因為它指的是全域物件,無論是否處於嚴格模式。

ECMAScript 模組中的頂層 this 始終被認為是無效的,因為它的值為 undefined

對於函式內的 this,此規則基本上會檢查包含 this 關鍵字的函式是否為建構函式或方法。 請注意,箭頭函式具有詞法 this,因此此規則會檢查它們的封閉環境。

此規則會根據以下條件判斷函式是否為建構函式

  • 函式的名稱以大寫字母開頭。
  • 函式被賦值給一個以大寫字母開頭的變數。
  • 該函式是 ES2015 類別的建構函式。

此規則會根據以下條件判斷函式是否為方法

  • 函式位於物件實體中。
  • 函式被賦值給一個屬性。
  • 該函式是 ES2015 類別的方法/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 的編譯器會強制執行此檢查。

請注意,從技術上講,TypeScript 只有在您啟用 strictnoImplicitThis 標誌時才會捕獲此錯誤。 這些標誌在大多數 TypeScript 專案中都已啟用,因為它們被認為是最佳實踐。

版本

此規則是在 ESLint v1.0.0-rc-2 中引入的。

資源

變更語言