Spells and Charms

プログラミング(呪文学)の学習記録。

this についての理解(1)

前回の記事で自分が次になにをすべきか確認したので早速thisからとりかかりました。

 

ahochauyo.hatenablog.com

 

 

( ・∇・)!

 

 

 

日本語の記事でわかりやすかったのはこちら。

takkyunさんという方の記事です。takkyun - Qiita

qiita.com

 

 

英語はこれがわかりやすかった。

Understanding Binding and 'this' in Javascript · GitHub

 

 

 

youtubeだとこちらわかりやすかったです。(英語)


WTF is THIS: Understanding the "this" keyword in JavaScript

 

 

 

 

 

thisのvalueは、シチュエーションによって変わるそうです。

 

( ・∇・)

 

 

 

ひとつめ。

Implicit Binding: dot notation is used to invoke a function

関数実行時に「 .  (ドット) 」がつかわれるパターン

 

→ 「 .  (ドット) 」の左側にあるものがthisのvalueになる。

 

 

 

先ほど紹介した英語の記事では

In implicit binding, whatever is to the left of the dot becomes the context for this in the function. 

Understanding Binding and 'this' in Javascript · GitHub

と大胆に書かれています。

 

 

 

 

dot notation で関数が呼ばれその中にthisがはいっているときはこのパターン。

冒頭で紹介したtakkyunさんの記事では、「this と function の関係」という章で書かれています。

 

サンプルコードをのせておきます。

 

例1

const student1 =
{
name : "Joe",
age: 20,
sayHello: function(){
console.log("Hello, " + this.name);
}
};

const student2 = {
name : "Elen",
age: 24,
sayHello: function(){
console.log("Hello, " + this.name);
}
};

const student3 = {
name : "Alex",
age: 19,
sayHello: function(){
console.log("Hello, " + this.name);
}
};


student1.sayHello(); // Hello, Joe
student2.sayHello(); // Hello, Elen
student3.sayHello(); // Hello, Alex

 

 

( ・∇・)

 

 

 

 

次。

 

 

 

Explicit Binding

関数実行時に.call( ), .apply( ), or .bind( )のいずれかが使われている場合。

これらは関数のメソッドです。

 

→ .call( ), .apply( ), .bind( )のカッコ内にある引数がthisのvalueになります。 

 

callとapplyの違いは、

call はargument listを受け入れるのに対して、applyは一つのarrayを受け入れる点だそうです。

Note: While the syntax of this function is almost identical to that of call(), the fundamental difference is that call() accepts an argument list, while apply() accepts a single array of arguments.

Function.prototype.apply() - JavaScript | MDN

 

 

冒頭で紹介したYouTubeの06:40以降でわかりやすく解説されています。

 

 

 

( ・∇・)

 

 

 

関数実行時に、別スコープにあるオブジェクトの情報をつかいたい。

そんな時にこの方法をつかうんですね。

 

explicit は明確にとか率直にという意味なので、
使いたいオブジェクトを明確に引数として渡す、みたいなイメージなのかもしれませんね。

 

 

 

サンプルコードです。
先ほどは、オブジェクト内のメソッドとしてfunctionが存在していましたが、今回は外側にあります。

 

 

例2


const sayHello = function(){
console.log("Hello, " + this.name);
}

const student1 =
{
name : "Joe",
age: 20
};

const student2 = {
name : "Elen",
age: 24
};

const student3 = {
name : "Alex",
age: 19
};

 

 

ここで仮に、先ほどと同様に、student1.sayHello(); と関数を呼び出してみたとします。

 

 


Uncaught TypeError: student1.sayHello is not a function

 

 

( ・∇・)?

 

 

エラーになりました。

 

 

 

sayHelloはfunctionではないと。。
sayHelloはfunctionで一番頭で宣言してるんですけど。。。

 

 

 

ただしい表現ではないかもしれないのですが、
student1.sayHello();というのは、student1のsayHelloを実行してという指示になります。

 

 

 

例2のコードをみていただくとstudent1 はメソッドをもっておりません。
なのでstudent1の中にsayHelloは存在していないため、エラーになるという理解を私はしました。

 

 

では、どうやったらsayHelloを実行できるのかとなりますが、
ここでメソッドをつかうんですね。

 

 

 

 

 ( ・∇・)!

 

 

 

 

sayHello.call(student1); // Hello, Joe
sayHello.call(student2); // Hello, Elen
sayHello.call(student3); // Hello, Alex

call をapply に変えても、この例の場合は同じ結果でした。

 

 

このときのthisは、引数として渡されたオブジェクトになってますね。

 

 

 

そして、.bind() ですが、これはちょっとややこしく、 .call()とほぼ同じなのですが、新しい関数を返してくるものになるそうです。

 

 

 

( ・∇・)?

 

 

 

 では試しに、先ほど試したcallをそのままbindに変更してみます。

 

 


sayHello.bind(student1); //


 

何もコンソールに表示されません。

エラーもなしです。

 

 

( ・∇・)?

 

 

 

無理やりコンソールしてみました。


console.log(sayHello.bind(student1));


 

t

 

f:id:ahochauyo:20190725162755p:plain

 

たしかに新しい関数になっています。

 

関数なので実行には()が必要ですよね。
ということでこちらで試してみます。

const sayHello = function(){
console.log("Hello, " + this.name);
}

const student1 =
{
name : "Joe",
age: 20
};

const student2 = {
name : "Elen",
age: 24
};

const student3 = {
name : "Alex",
age: 19
};



sayHello.bind(student1)();
sayHello.bind(student2)();
sayHello.bind(student3)();

 

 

これはどうなるでしょう?

 

 

 

 

 

( ・∇・)

 

 

 

f:id:ahochauyo:20190725163727p:plain

 

 

ででーん!
いけましたね。

 

 

 

ちなみに、多くの場合は変数に代入して使うみたいです。

const helloJoe = sayHello.bind(student1);
const helloElen = sayHello.bind(student2);
const helloAlex = sayHello.bind(student3);

helloJoe();
helloElen();
helloAlex();

 

 実行結果は同じです。

 

 

 

 

 

最後です。

 

thisにはデフォルトがあるらしいです。

 

Default Binding:

thisを含む関数を実行するけれども、dot notation もつかわず、call(), apply(), bind()もつかっていないとき。

 

 

→ デフォルトでWindowオブジェクトがthisのvalue。もしstrict modeが適用されているなら、undefined。

 

 

ためしにコンソールでthisとうってみました。

 

f:id:ahochauyo:20190725162038p:plain

 

 

 

 

( ・∇・)!

 

 

 

 

 

これがめちゃくちゃわかりやすいので、そのままはっておきます。

 

  1. Is there a dot? Look to the left. That's this.
  2. Do you see .call() or .apply()? What's passed in before the first comma? Thats this.
  3. Does the function stand alone when it's invoked? Then what's your global context? That's this.

Understanding Binding and 'this' in Javascript · GitHub

 

 

だいぶ長くなりました。
読んでいただきありがとうございます。