主な違いは、「this
は矢印関数で字句的にバインドされている」ということです。それはすべて順調ですが、実際にはそれが何を意味するのかわかりません。
私はそれが関数の本体を定義する中括弧の範囲内で一意であることを知っていますが、太い矢印を参照していない限り、this
が何を参照しているかわからないので、実際に次のコードの出力を伝えることができませんでした関数自体....これは有用ではないようです。
var testFunction = () => { console.log(this) };
testFunction();
矢印関数は、囲んでいるコンテキストのthis
値をキャプチャします
function Person(){
this.age = 0;
setInterval(() => {
this.age++; // |this| properly refers to the person object
}, 1000);
}
var p = new Person();
したがって、質問に直接答えるために、矢印関数内のthis
は、矢印関数が割り当てられる直前と同じ値になります。
全体像を提供するために、動的バインディングと字句バインディングの両方について説明します。
this
は、メソッドが呼び出されるオブジェクトを参照します。これは、SOで定期的に読まれる文です。しかし、それはまだフレーズであり、かなり抽象的なものです。この文に対応するコードパターンはありますか?
はいあります:
_const o = {
m() { console.log(this) }
}
// the important patterns: applying methods
o.m(); // logs o
o["m"](); // logs o
_
m
はthis
に依存しているため、メソッドです。 o.m()
またはo["m"]()
は、m
がo
に適用されることを意味します。これらのパターンは、有名なフレーズへのJavascriptの翻訳です。
次のことに注意する必要がある別の重要なコードパターンがあります。
_"use strict";
const o = {
m() { console.log(this) }
}
// m is passed to f as a callback
function f(m) { m() }
// another important pattern: passing methods
f(o.m); // logs undefined
f(o["m"]); // logs undefined
_
前のパターンと非常によく似ており、括弧のみが欠落しています。しかし、結果はかなりのものです。m
を関数f
に渡すと、そのオブジェクト/コンテキストm
のout o
を引き出します。現在はルート化されており、this
は何も参照していません(厳密モードが想定されます)。
矢印関数には、独自のthis
/super
/arguments
バインディングがありません。親のレキシカルスコープからそれらを継承します。
_const toString = Object.prototype.toString;
const o = {
foo: () => console.log("window", toString.call(this)),
bar() {
const baz = () => console.log("o", toString.call(this));
baz();
}
}
o.foo() // logs window [object Window]
o.bar() // logs o [object Object]
_
グローバルスコープ(ブラウザのWindow
)以外に、関数のみがJavascript(およびES2015の_{}
_ブロック)でスコープを形成できます。 _o.foo
_矢印関数が呼び出されると、baz
がthis
を継承できる周囲の関数はありません。したがって、this
オブジェクトにバインドされているグローバルスコープのWindow
バインディングをキャプチャします。
baz
が_o.bar
_によって呼び出されると、矢印関数は_o.bar
_で囲まれ(_o.bar
_は親レキシカルスコープを形成します)、_o.bar
_のthis
バインディング。 _o.bar
_はo
で呼び出されたため、そのthis
はo
にバインドされます。
このコードショーで、より明確なアイデアが得られることを願っています。基本的に、矢印関数の「this」は「this」の現在のコンテキストバージョンです。コードを参照してください:
// 'this' in normal function & arrow function
var this1 = {
number: 123,
logFunction: function () { console.log(this); },
logArrow: () => console.log(this)
};
this1.logFunction(); // Object { number: 123}
this1.logArrow(); // Window
矢印関数this
はEs6の周囲の親を指しています。これは、ES5の匿名関数のようにスコープしないことを意味します...
これは、ES5で広く使用されているvar selfをこれに割り当てることを避けるための非常に便利な方法です...
次の例を見て、オブジェクト内に関数を割り当てます。
var checkThis = {
normalFunction: function () { console.log(this); },
arrowFunction: () => console.log(this)
};
checkThis.normalFunction(); //Object {}
checkThis.arrowFunction(); //Window {external: Object, chrome: Object, document: document, tmpDebug: "", j: 0…}
以下の方法で理解することができます
// whatever here it is, function or fat arrow or literally object declare
// in short, a pair of curly braces should be appeared here, eg:
function f() {
// the 'this' here is the 'this' in fat arrow function below, they are
// bind together right here
// if 'this' is meaningful here, eg. this === awesomeObject is true
console.log(this) // [object awesomeObject]
let a = (...param) => {
// 'this is meaningful here too.
console.log(this) // [object awesomeObject]
}
したがって、太い矢印関数の「this」はバインドされていません。つまり、ここで「this」にバインドすることはできません。applyはできません。 太い矢印関数の「this」は、テキストエディタでコードテキストを書き留めるときにバインドされます。ここでは、太い矢印関数の「this」は文字通り意味があります。ここでテキストエディターでコードを記述すると、アプリがreplでそこで実行されます。 テキストエディターで変更しない限り、ファットアラーでバインドされた「this」は変更されません。私のプール英語でごめんなさい...
矢印関数はthis
キーワードとバインドしません
var env = "globalOutside";
var checkThis = {env: "insideNewObject", arrowFunc: () => {
console.log("environment: ", this.env);
} }
checkThis.arrowFunc() // expected answer is environment: globalOutside
// Now General function
var env = "globalOutside";
var checkThis = {env: "insideNewObject", generalFunc: function() {
console.log("environment: ", this.env);
} }
checkThis.generalFunc() // expected answer is enviroment: insideNewObject
// Hence proving that arrow function never binds with 'this'
別の例では、下の年齢ボタンをクリックすると
<script>
var person = {
firstName: 'John',
surname: 'Jones',
dob: new Date('1990-01-01'),
isMarried: false,
age: function() {
return new Date().getFullYear() - this.dob.getFullYear();
}
};
var person2 = {
firstName: 'John',
surname: 'Jones',
dob: new Date('1990-01-01'),
isMarried: false,
age: () => {
return new Date().getFullYear() - this.dob.getFullYear();
}
};
</script>
<input type=button onClick="alert(person2.age());" value="Age">
このような例外をスローします
×JavaScriptエラー:Uncaught TypeError:18行目のundefinedのプロパティ 'getFullYear'を読み取れません
しかし、person2のこの行を変更すると
return new Date().getFullYear() - this.dob.getFullYear();
に
return new Date().getFullYear() - person2.dob.getFullYear();
person2でこのスコープが変更されたため、機能します