質問: new Dragon2(); boss2.attack(); // 2...ドラゴンの攻撃! ドラゴンのHPは200だ! ``` このように同じ結果が得られています。 こういう感じの理解しかできておらず、使いどころがイメージ出来ていません。 すみませんが、ご教示よろしくお願いします。
回答: 結論から言えば上の例(callを使った方)が良いですね。 上の例と下の例は応用した時に違いが生まれます。 ``` // 上の例 var hoge; hoge = boss2.attack; hoge() // 2...ドラゴンの攻撃! ドラゴンのHPはundefinedだ! // 下の例 var hoge; hoge = boss2.attack; hoge() // 2...ドラゴンの攻撃! ドラゴンのHPは200だ! ``` HPはundefinedって超絶強そうですね(小並感 callを使った上の例の場合、そのものにスコープが行きます。 これはbossのHPを変更した場合に顕著になります。 ``` var hoge; boss2.hp = 3000; boss2.attack(); // 2...ドラゴンの攻撃! ドラゴンのHPは3000だ! hoge = boss2.attack; hoge(); // 2...ドラゴンの攻撃! ドラゴンのHPはundefinedだ! ``` callを使わない下の例の場合、こうなります。 ``` var hoge; boss2.hp = 3000; boss2.attack(); // 2...ドラゴンの攻撃! ドラゴンのHPは3000だ! hoge = boss2.attack; hoge(); // 2...ドラゴンの攻撃! ドラゴンのHPは200だ! ``` これはTeki2の下位概念にDragon2インスタンスが作られ、boss2という名前が与えられますが、 boss2自体のプロパティにはhpは存在しません。 なのでスコープチェーンに従い、boss2の上位にあるTeki2.hpの値が利用されます。 しかし、今回`boss2.hp = 3000`と外部からboss2インスタンス自体のプロパティをいじったので、 boss2.hpは3000だけど、Teki2.hpは200というチグハグな状況が生まれます。 これを「種族HPだからMaxHPは親を辿って参照しよう!」という使い方も考えられますが、ちょっとイレギュラーなのでやめておいたほうがいいかと思います。 お次はapplyの解説です。 ぶっちゃけQiitaの記事がまとまり過ぎてて説明する余地がほぼ無いのですが... 関数型プログラミングとJavaScriptは相性が非常に良く、私は大抵のケースをリスト操作で片付けます。 リスト操作を覚えれば、殆どのケースでfor文を使う必要がなくなります。 applyは配列から関数を叩ける、thisを誘導出来るという2点が魅力です。 その結果、配列を持ってて加工したいケースが多いのでapplyは重宝します。 例として生徒の国語の最高得点、最低得点、平均点をJavaScriptで求めてみましょう。 今回は前者の「配列から関数を叩ける」点がメリットとして働いている事が分かるかと思います。 多少イディオムを使っているとはいえ、たったこれだけの行数で済むのは力強いですね。 ``` var user1 = { kokugo: 80, sugaku: 75 }; var user2 = { kokugo: 85, sugaku: 60 }; var user3 = { kokugo: 40, sugaku: 90 }; var users = [user1, user2, user3]; // こういうケースはNode.jsやSPAでJSのカバー範囲が広くなると頻出します var output_nums = function (nums) { var mean = function () { var plus = function (a, b) {return a + b;}; var sum = Array.prototype.slice.call(arguments).reduce(plus); return Math.round(sum / arguments.length); } console.log(Math.max.apply(null, nums)); console.log(Math.min.apply(null, nums)); console.log(mean.apply(null, nums)); } output_nums(users.map(function(it){return it.kokugo})); // 85 // 40 // 68 ```