web-dev-qa-db-ja.com

矢印関数とこれ

ES6を試しているのですが、関数内に次のようなプロパティを含めたいと思います。

var person = {
  name: "jason",

  shout: () => console.log("my name is ", this.name)
}

person.shout() // Should print out my name is jason

ただし、このコードコンソールを実行すると、ログはmy name isのみになります。私は何が間違っているのですか?

20
jason328

簡単な答え:thisは最も近い境界thisを指します-提供されたコードでは、thisは囲んでいるスコープにあります。

長い答え:矢印関数 作成時にthisをバインドしますthisarguments、またはその他の特別な名前がバインドされていませんまったく -オブジェクトが作成されているときに、名前thisが囲んでいるスコープにありますpersonオブジェクト。宣言を移動すると、これをより明確に確認できます。

var person = {
  name: "Jason"
};
person.shout = () => console.log("Hi, my name is", this);

そして、ES5の矢印構文の漠然とした近似に変換すると、さらに明確になります。

var person = {
  name: "Jason"
};
var shout = function() {
  console.log("Hi, my name is", this.name);
}.bind(this);
person.shout = shout;

どちらの場合も、this(shout関数の場合)は、personオブジェクトに追加されたときに関数がアタッチされる新しいスコープではなく、personが定義されているのと同じスコープを指します。

あなたcannot矢印関数をそのように機能させるが、@ kamituelが 彼の答え で指摘しているように、あなたcanを利用する同様のスペース節約を得るためのES6の短いメソッド宣言パターンの例:

var person = {
  name: "Jason",
  // ES6 "method" declaration - leave off the ":" and the "function"
  shout() {
    console.log("Hi, my name is", this.name);
  }
};
30
Sean Vieira

@Sean Vieiraに同意しました-この場合、thisはグローバルオブジェクトにバインドされます(または、コメントで指摘されているように、より一般的には囲んでいるスコープにバインドされます)。

構文を短くしたい場合は、別のオプションがあります。拡張オブジェクトリテラルは、プロパティ関数の短い構文をサポートします。 thisは、期待どおりにバインドされます。 shout3()を参照してください:

window.name = "global";

var person = {
    name: "jason",

    shout: function () {
        console.log("my name is ", this.name);
    },
    shout2: () => {
        console.log("my name is ", this.name);
    },
    // Shorter syntax
    shout3() {
        console.log("my name is ", this.name);
    }
};

person.shout();  // "jason"
person.shout2(); // "global"
person.shout3(); // "jason"
23
kamituel

受け入れられた答えは素晴らしく、簡潔で、明確ですが、ショーン・ビエイラが言ったことについて少し詳しく説明します。

矢印関数には、この引数やその他の特別な名前はまったくバインドされていません。

矢印関数には「this」がないため、親の「this」を使用します。 「this」は常に親を指し、personオブジェクトの親はWindowです(ブラウザを使用している場合)。

これをコンソールで実行することを証明するには:

var person = {
    name: "Jason",
    anotherKey: this
}
console.log(person.anotherKey)

Windowオブジェクトを取得します。

私はこれがそれについて考えるのに本当に役立つ方法だと思います。オブジェクトリテラルの「これ」が何であるかは別の議論であるため、それは完全な話ではありません。

8
Tenbrink

ここで、関数内のこの値は、矢印関数が使用される場所ではなく、定義される場所によって決定されます。

したがって、thisは、他の名前空間にラップされていない場合、グローバル/ウィンドウオブジェクトを参照します

2
A.B

問題は、( [〜#〜] mdn [〜#〜]

矢印関数式[...]は、この値を字句的にバインドします。

矢印関数は、囲んでいるコンテキストのこの値をキャプチャします。

したがって、その関数のthisの値は、オブジェクトリテラルを作成するthisの値になります。おそらく、それは非厳密モードではwindowになり、厳密モードではundefinedになります。

これを修正するには、通常の機能を使用する必要があります。

var person = {
  name: "jason",
  shout: function(){ console.log("my name is ", this.name) }
}
person.shout();
0
Oriol