• Skip to main content
  • Skip to primary sidebar

プログラミング入門ナビ

プログラミング学習初心者のための情報メディア

You are here: Home / Archives for 呼び出し

呼び出し

JavaScriptの「this」は呼び出し方によって値が変わる?違いを徹底解説!

2020-05-29 By プログラミング入門ナビ編集部

はじめに

指し示す指

JavaScriptの「this」は他の言語と比較し挙動に少々癖があります。呼び出し方によってどの値を指すかが変わるためです。

思ったような値が得られない時は、thisの呼び出し方に問題があるかもしれません。

この記事では呼び出し方の違いによるthisの挙動を説明します。

thisの呼び出し方:基礎編

まずはよく使われるオーソドックスな呼び出し方を見ていきましょう。

基礎編クイズ

value = 1;
var obj = {
  value: 2,
  func: function() { console.log(this.value) }
}
function func() { console.log(this.value) }
var test = obj.func;

console.log(this.value);    //①
obj.func();                 //②
test();                     //③
func();                     //④

上記①②③④では何が表示されるでしょうか。少し考えてみてください。

答えは下記のようになります。

> 1       //①
> 2       //②
> 1       //③
> 1       //④

正解できましたか?

①②③④はいずれもthis.valueの呼び出しをしていますが、この通り表示される値が違います。なぜこのようになるのか、順を追って説明していきます。

グローバルコンテキストでの呼び出し

①ではthisをグローバルコンテキスト(関数やオブジェクトの外側)で呼び出しています。この場合、thisにはグローバルオブジェクトが入ります。

グローバルオブジェクトはJavaScriptが実行される環境により変わるのですが、ブラウザの場合はWindowオブジェクトとなります。

下記のようにconsole.logでthisを表示させればグローバルオブジェクトが何なのか確認できます。

console.log(this);    //> [object Window]が表示される

今回は1行目でvalue = 1;としたことで、このグローバルオブジェクトにvalueという値が定義され1が代入されていたため1が表示されました。

このように、グローバルコンテキストでthisを呼び出すと、グローバルオブジェクトが入ります。

オブジェクトのメソッド呼び出し

②は「objオブジェクトのfunc」をメソッド呼び出しています。

このように「〇〇.func();」といった具合で関数呼び出しの前に「〇〇.」がつく場合、関数「func」のスコープ内でのthisが指すのは前置きの〇〇が示すオブジェクトです。

この例ではobjのfunc関数スコープ内でthisが呼び出されているので、このthisが指すのは自分自身であるobjオブジェクトですね。

そしてobjは自身のvalueを持つため、結果的にthis.valueはこれを呼び出して2が入ります。

③は同じくobjの中で定義されたfuncを実行しているのですが、testにobj.funcを代入したあとでtest();と前置きなしで呼び出されていますね。

このように、グローバルコンテキストで前置きなしに関数だけが呼び出されている場合の関数内thisは、次項の「関数呼び出し」のケースにあたりグローバルオブジェクトを指すため1が表示されます。

関数呼び出し

④はグローバルコンテキストで定義された関数funcを呼び出しています。メソッド呼び出しではないので、「〇〇.」のような前置きはありません。

この場合の関数内thisもグローバルオブジェクトを指します。

グローバルオブジェクト(ブラウザで実行の場合はWindowオブジェクト)のvalueは一行目で定義されている通り1なので、1が表示されるわけです。

thisの呼び出し方:応用編

基礎編で見たように、thisの挙動は呼び出し方によって変わります。thisに何を入れたいかを明示的に指定するためのいくつかの方法を紹介します。

アロー関数呼び出し

ES6からはアロー関数が使用できるようになりました。関数としての基本的な挙動は通常の関数(function)と変わらないのですが、関数スコープ内のthisについては挙動が異なります。

アロー関数の中で呼び出されたthisは、関数の呼び出され方に関わらず、その関数が最初に定義された時点で指していた対象を指し続けるのが特徴です。

例を見てみましょう。

value = 5;
function func1() { console.log(this.value) }
var func2 =()=> { console.log(this.value) }
var obj1 = {
  value: 1,
  func1
}
var obj2 = {
  value: 2,
  func2
}

obj1.func1();   //1が表示される
obj2.func2();   //5が表示される

func1は従来の関数、func2はアロー関数です。この時点では両方ともグローバルコンテキストで定義されているため、thisはグローバルオブジェクトを指します。

その後に2種類のオブジェクト:obj1とobj2が定義され、それぞれfunc1とfunc2を保有していますね。

obj1のメソッド呼び出しでは、基礎編で触れたようにthisはobj1を指すので、obj1が持つvalueの値である1が表示されます。

これに対し、obj2のメソッド呼び出しではfunc2がアロー関数なので、thisが指すのはobj2でなく定義された時点で指していたグローバルオブジェクトのままです。

結果として、ojbのvalue(値は2)でなく、グローバルのvalue(値は5)が表示されます。

このように、アロー関数を使うと呼び出され方によらずthisが指す対象を定義当初のまま固定できるのです。

関数のコンストラクタ呼び出し

関数をグローバルコンテキストで前置き無しに呼び出すとその関数内でのthisはグローバルオブジェクトを指すのでした。

しかし、関数をコンストラクタ呼び出しすると、関数自体がインスタンスとなりthisは自身を指すようになります。

function Obj() {  console.log(this) }
Obj();      //> [object Window]が表示される
var obj = new Obj();    //> [object Object]が表示される

1行目の関数を2行目で呼び出した場合はthisはグローバルオブジェクトであるWindowオブジェクトになりますが、3行目のようにコンストラクタ呼び出しをするとObjectオブジェクトとなっていることが分かりますね。

実際に通常の関数呼び出しとコンストラクタ呼び出しの挙動を比較してみましょう。

function MyObject(num){
  this.value = num;
  console.log(this.value);
  this.show = function() { console.log(this.value) };
}
MyObject(5);        //5が表示される
var myObj = new MyObject(3);    //3が表示される
console.log(this.value);    //5が表示される
myObj.show();       //3が表示される

6行目が通常の関数呼び出し、7行目がコンストラクタ呼び出しです。

関数MyObjectではthis.valueに引数の値を代入しますが、通常呼び出しではグローバルオブジェクトのvalueに、コンストラクタ呼び出しでは自身(MyObjectのインスタンス)のvalueに値を入れています。

そのため6行目・8行目ではグローバルvalueが呼ばれるので5が、7行目・9行目ではMyObjectインスタンスのvalueが呼ばれるので3が表示されるわけです。

apply・call関数を使った呼び出し

関数呼び出しにおいてthisに何を入れるか明示的に指定できるのがapply関数とcall関数です。

使い方を見てみましょう。

value = 0;
var obj1 = { value: 1 };
var obj2 = { value: 2 };
function func() { console.log(this.value) }

func();             //0が表示される
func.call(obj1);    //1が表示される
func.apply(obj2);   //2が表示される

4行目の関数funcのthisはグローバルオブジェクトを指すので、6行目のように呼び出すとグローバルのvalueである0が表示されますね。

一方、7行目・8行目のようにcallやapply関数を使って呼び出すと引数に指定したオブジェクトをthisとして指定することができるので、それぞれobj1・obj2のvalueである1と2を表示します。

call・applyでは関数に渡す引数を設定することもでき、その方法によりこれらを使い分けます。詳しくはドキュメント(MDN)を参照してください。

まとめ

考える女性

JavaScriptでのthisについて、呼び出し方による挙動の違いを説明しました。

最初は理解しにくいので、実際にコードを書いて試していくのがおすすめです。

動画で学ぶプログラミング入門

オンラインスクールProglus(プログラス)でプログラミングを学んで、創れる人になろう!

在宅学習応援!今なら複数の基礎コースが無料!!

今すぐ詳細を確認する

Filed Under: プログラミング入門 Tagged With: JavaScript, this, 呼び出し

Primary Sidebar

Twitter

Follow @programmingnavi Tweets by programmingnavi

Facebookページ

プログラミング入門ナビ

メルマガに今すぐ登録!

ブログの更新情報やお得なクーポン情報などをお知らせします。

登録はこちらから。

人気の記事

まだデータがありません。

最近の投稿

  • 【7/9更新】Udemyプログラミング入門講座等の割引クーポン配布
  • JavaScriptの「this」は呼び出し方によって値が変わる?違いを徹底解説!
  • JavaScriptのfor文で配列要素の足し算をするとNaNが出るのはなぜ?原因と対処法を解説!
  • プログラミング学習を成功させるポイントを3つお送りいたします
  • 初心者がスマホアプリを開発するには?iOSとAndroidの両方について必要なスキルを確認しよう

カテゴリー

  • エンジニアのしごと
  • エンジニアへの道
  • ツールの使い方
  • ニュース
  • プログラミング入門

タグクラウド

AI AWS AWS Cloud9 Bootstrap Cloud9 CodeWing CSS Git GitHub Heroku HTML JavaScript Linux macOS MySQL MySQL Workbench node.js Nuxt.js Proglus Python Ruby Ruby on Rails SQL Udemy Vue.js Web開発 Windows Windows10 エラー エンジニア オンライン学習 サーバ サーバー スクリーンショット セキュリティ セール データベース プログラミング プログラミング入門 プログラミング学習 ユーデミー 初心者 未経験 機械学習 開発環境構築

アーカイブ

  • 2020年7月
  • 2020年5月
  • 2020年4月
  • 2020年3月
  • 2020年2月
  • 2020年1月
  • 2019年11月
  • 2019年9月
  • 2019年7月
  • 2019年6月
  • 2019年5月
  • 2019年4月
  • 2019年3月
  • 2019年2月
  • 2019年1月
  • 2018年12月
  • 2018年11月
  • 2018年10月
  • 2018年9月
  • 2018年8月
  • 2018年7月
  • 2018年6月
  • 2018年5月
  • 2018年4月
  • 2018年3月

検索

Copyright © 2025 · programmingnavi.com ・About・プライバシーポリシー