矢印関数はscope
、関数を単純化し、this
キーワードをより単純にすることで解決するために作成されました。=>
矢印のような構文を使用します。
注:既存の機能に代わるものではありません。すべての関数構文を矢印関数に置き換えると、すべてのケースで機能するわけではありません。
既存のES5構文を見てみましょう。this
キーワードがオブジェクトのメソッド(オブジェクトに属する関数)内にある場合、それは何を参照しますか?
var Actor = {
name: 'RajiniKanth',
getName: function() {
console.log(this.name);
}
};
Actor.getName();
上記のスニペットはを参照object
し、名前を出力し"RajiniKanth"
ます。以下のスニペットを調べて、これがここで何を指摘するかを見てみましょう。
var Actor = {
name: 'RajiniKanth',
movies: ['Kabali', 'Sivaji', 'Baba'],
showMovies: function() {
this.movies.forEach(function(movie) {
alert(this.name + " has acted in " + movie);
});
}
};
Actor.showMovies();
では、this
キーワードが内部にある場合はmethod’s function
どうでしょうか。
ここでは、これはから落ちwindow object
たものinner function
として参照しscope
ます。なぜならthis
、この場合、関数の所有者を常に参照しているからです。この場合は、スコープの外にあるため、ウィンドウ/グローバルオブジェクトです。
object
のメソッド内にある場合— function
の所有者がオブジェクトです。したがって、thisキーワードはオブジェクトにバインドされます。それでも、それが関数の内部にある場合、スタンドアロンまたは別のメソッド内では、常にwindow/global
オブジェクトを参照します。
var fn = function(){
alert(this);
}
fn(); // [object Window]
この問題を私たちES5
自身で解決する方法はいくつかあります。ES6の矢印関数の詳細を説明する前に、その解決方法を見てみましょう。
通常は、メソッドの内部関数の外部に変数を作成します。これで、‘forEach’
メソッドthis
はobject’s
プロパティとその値にアクセスできるようになりました。
var Actor = {
name: 'RajiniKanth',
movies: ['Kabali', 'Sivaji', 'Baba'],
showMovies: function() {
var _this = this;
this.movies.forEach(function(movie) {
alert(_this.name + " has acted in " + movie);
});
}
};
Actor.showMovies();
を使用bind
しthis
て、メソッドを参照するキーワードをにアタッチしmethod’s inner function
ます。
var Actor = {
name: 'RajiniKanth',
movies: ['Kabali', 'Sivaji', 'Baba'],
showMovies: function() {
this.movies.forEach(function(movie) {
alert(this.name + " has acted in " + movie);
}.bind(this));
}
};
Actor.showMovies();
今でES6
矢印機能、我々は対処することができますlexical scoping
簡単な方法で問題。
var Actor = {
name: 'RajiniKanth',
movies: ['Kabali', 'Sivaji', 'Baba'],
showMovies: function() {
this.movies.forEach((movie) => {
alert(this.name + " has acted in " + movie);
});
}
};
Actor.showMovies();
Arrow functions
bind
thisがであることを除いて、関数ステートメントに似ていますparent scope
。場合はarrow function is in top scope
、this
引数が参照されますwindow/global scope
、通常の関数内の矢印機能ながら、その外側の関数としてのこの引数は同じになります。
arrow
関数を使用するthis
とscope
、作成時に囲みにバインドされ、変更できません。新しい演算子bind、call、applyはこれには影響しません。
var asyncFunction = (param, callback) => {
window.setTimeout(() => {
callback(param);
}, 1);
};
// With a traditional function if we don't control
// the context then can we lose control of `this`.
var o = {
doSomething: function () {
// Here we pass `o` into the async function,
// expecting it back as `param`
asyncFunction(o, function (param) {
// We made a mistake of thinking `this` is
// the instance of `o`.
console.log('param === this?', param === this);
});
}
};
o.doSomething(); // param === this? false
上記の例では、これの制御を失っています。上記の例は、の変数参照this
またはを使用して解決できますbind
。ES6を使用するとthis
、のバインド先としてを簡単に管理できlexical scoping
ます。
var asyncFunction = (param, callback) => {
window.setTimeout(() => {
callback(param);
}, 1);
};
var o = {
doSomething: function () {
// Here we pass `o` into the async function,
// expecting it back as `param`.
//
// Because this arrow function is created within
// the scope of `doSomething` it is bound to this
// lexical scope.
asyncFunction(o, (param) => {
console.log('param === this?', param === this);
});
}
};
o.doSomething(); // param === this? true
Arrow関数を使用しない場合
オブジェクトリテラルの内部。
var Actor = {
name: 'RajiniKanth',
movies: ['Kabali', 'Sivaji', 'Baba'],
getName: () => {
alert(this.name);
}
};
Actor.getName();
Actor.getName
矢印関数で定義されていますが、ため、呼び出し時に、それは未定義の警告this.name
であるundefined
コンテキストがに残るようwindow
。
これは、矢印関数がコンテキストを語彙的にwindow object
...外部スコープにバインドするために発生します。実行this.name
はwindow.name
未定義のと同等です。
オブジェクトのプロトタイプ
にメソッドを定義する場合も同じ規則が適用されますprototype object
。代わりに、誤っをもたらすsayCatName方法を、定義するための矢印機能を使用しますcontext window
:
function Actor(name) {
this.name = name;
}
Actor.prototype.getName = () => {
console.log(this === window); // => true
return this.name;
};
var act = new Actor('RajiniKanth');
act.getName(); // => undefined
コンストラクターの呼び出し
this
構築呼び出しでは、新しく作成されたオブジェクトです。new Fn()を実行すると、のコンテキストはconstructor Fn
新しいオブジェクトですthis instanceof Fn === true
。
this
囲んでいるコンテキスト、つまり、新しく作成されたオブジェクトに割り当てられないようにする外部スコープからセットアップされます。
var Message = (text) => {
this.text = text;
};
// Throws "TypeError: Message is not a constructor"
var helloMessage = new Message('Hello World!');
動的コンテキストによるコールバック
アロー関数はcontext
宣言時に静的にバインドし、動的にすることはできません。イベントリスナーをDOM要素にアタッチすることは、クライアント側のプログラミングでは一般的なタスクです。イベントは、これをターゲット要素としてハンドラー関数をトリガーします。
var button = document.getElementById('myButton');
button.addEventListener('click', () => {
console.log(this === window); // => true
this.innerHTML = 'Clicked button';
});
this
グローバルコンテキストで定義されるアロー関数のウィンドウです。クリックイベントが発生すると、ブラウザーはボタンコンテキストでハンドラー関数を呼び出そうとしますが、矢印関数は事前定義されたコンテキストを変更しません。this.innerHTML
と同等window.innerHTML
であり、意味がありません。
ターゲット要素に応じてこれを変更できる関数式を適用する必要があります。
var button = document.getElementById('myButton');
button.addEventListener('click', function() {
console.log(this === button); // => true
this.innerHTML = 'Clicked button';
});
ユーザーがボタンをクリックすると、ハンドラー関数ではこれがボタンになります。したがってthis.innerHTML = 'Clicked button'
、ボタンのテキストを正しく変更して、クリックされたステータスを反映します。
参照:https :
//dmitripavlutin.com/when-not-to-use-arrow-functions-in-javascript/
Fixed this bound to scope at initialisation
は制限として考えますか?