はじめに
こんにちは、Ebataです。
この記事は遊戯王で遊んだことがあり、かつコールスタック内でのコンテキストの生成や消滅タイミングの理解が難しい、という狭すぎるターゲット層に届けたい記事です。
技術書を読んでいる時に、「あれ、なんか見たことあるなぁ」と思ったので共有いたします。(これTwitterでも良くない?)
コンテキストとは
そもそも、「コンテキストって何?」という方に向けて、簡単に解説します。
プログラミングの分野でも、同じコード記述やプログラム上の要素が、その置かれているプログラム内での位置や、実行される際の内部状態などによって異なる振る舞いをしたり、異なる制約を受けたりすることを指してコンテキストということがある。
つまり同じコードでも、環境が違えば違うルールのもとで実行される、ということですね。
記事内でのコンテキストは、このルール・制約のことを指しています。
コールスタックとは
関数内で他の関数を呼び出すときの階層です。
例えば、
function first(){
second();
}
function second(){
third();
}
...
first(); //関数を呼び出す
このようなコードがあった場合、first()
がsecond()
を呼び出して、second()
がthird()
を呼び出して……。
といったように、階層的に表すことができます。これをコールスタックと言います。
コールスタックとコンテキストの関係
「コールスタックとコンテキストはなんとなく分かった。で、どういう関係なの?」
階層表示された関数ごとに、コンテキストが存在する。ということです。変数は参照できるか、などの制約が変わります。
一番分かりやすいのは、this
が何を参照するのか、ではないでしょうか。
//グローバルコンテキストでは、thisはwindowを参照。
console.log(this === window);
> true
//メソッドコンテキストでは、ichiroを参照。
const ichiro = {
name: "一郎",
hello: function(){
console.log("こんにちは、" + this.name);
}
}
ここで、この記事の内容です。
コールスタックでは、呼び出された順番にコンテキストが生成されます。
function first(){
second();
}
fuction second(){
third();
}
function third(){
//処理
}
first();
この時、
-
first()
のコンテキスト生成 -
second()
のコンテキスト生成 -
third()
のコンテキスト生成 -
third()
のコンテキスト消滅 -
second()
のコンテキスト消滅 -
first()
のコンテキスト消滅
といった流れになります。
遊戯王のチェーン処理
ここからは本当に関係ないのですが、先述したコンテキストの生成・消滅の流れが「遊戯王のチェーン処理」に似ていると感じた話です。
遊戯王には、攻撃や効果の発動に対して効果を発動する、「チェーン」と呼ばれる処理があります。
例えば、モンスターの攻撃
に対してトラップカード
を発動し、そのトラップカードに対してトラップカードを発動することが可能です。
//ライフポイントは8000。
my_life = 8000;
enemy_life = 8000;
//攻撃に対して発動するトラップカード。
const magic_cylinder = {
name: "マジックシリンダー",
type: "トラップカード",
effect: function(){
/*
相手モンスターの攻撃宣言時、攻撃モンスター1体を対象として発動できる。
その攻撃モンスターの攻撃を無効にし、その攻撃力分のダメージを相手に与える。
*/
}
}
//トラップカードに対して発動するトラップカード。
const solemn_judgment = {
name: "神の宣告",
type: "トラップカード",
effect: function(){
/*
LPを半分払って以下の効果を発動できる。
魔法・罠カードが発動した時に発動できる。
その発動を無効にし破壊する。
*/
}
}
//攻撃するモンスター。
const blue_eyes_white_dragon = {
name: "ブルーアイズホワイトドラゴン",
type: "通常モンスター",
atk: 3000,
def: 2500
}
function kougeki()=>{
//攻撃する。
}
//攻撃後の処理。
function attack(monster){
//①monsterが攻撃する。
kougeki();
//②マジックシリンダーの発動。
magic_cylinder.effect;
//③神の宣告の発動。
solemn_judgment.effect;
}
//ブルーアイズの攻撃。
attack(blue_eyes_white_dragon);
長々と書きましたが、
-
ブルーアイズホワイトドラゴン
の攻撃。 -
マジックシリンダー
の効果発動。 -
神の宣告
の効果発動。
この順番で発動され、
ブルーアイズホワイトドラゴン
の攻撃を、マジックシリンダー
で無効にし跳ね返す。この処理を神の宣告
でさらに無効にする、という流れになります。
なので、このチェーン処理の順番は、
-
神の宣告
の効果でマジックシリンダー
無効。 -
マジックシリンダー
は無効される。 -
ブルーアイズホワイトドラゴン
の攻撃が通る。
となります。
この流れが、先述した『コールスタックでのコンテキスト生成・消滅のタイミング』に似ていますよね。
遊戯王をやっている方は、こう考えていただけると分かりやすいと思います。
終わりに
全然内容はありませんでしたが、個人的には大満足の記事になりました。こんな記事も誰かに読んでいただけたなら嬉しいです。
あと、まだ駆け出しなのでコードが汚いとかはご愛嬌。。。(成長します)