Help us understand the problem. What is going on with this article?

JavaScriptを始めるに当たってのハマりポイント

More than 3 years have passed since last update.

はじめまして。BRIGHT VIEでサーバサイドのエンジニアをしている @lemonade14 です。

BRIGHT VIE エンジニア Advent Calendar 2016の7日目の記事となります。

弊社の開発環境

弊社の最近の開発では、JavaScriptを中心とした技術でサービスの開発を行っています。

サーバサイドはNodeJS(ver6.0.0)、フロントエンドはAngularJS(1系)、アプリ側はSwiftを用いたWebViewで開発を進めています。

これまでJavaScriptと言えば、jQueryを中心としたUI構成やDOMのアクセス、
アニメーションの実行など簡単なものがメインでしたが、
近年のモダンな開発におけるJavaScriptは設計概念や言語仕様、パフォーマンスチューニングなど
JavaScriptのスキルもかなりレベルの高いものになってきていると感じています。

自分自身もここ1~2年ほど、JavaScriptのモダンな開発に着手し、
SPA(Single Page Application)での開発を続けてきましたが、
新規メンバーの参入やPHPなどのサーバプログラマーがJavaScriptを始めるにあたり、
「かなり苦労しているなぁ」とか「これ毎回教えているなぁ」と感じる部分について記載できればと思います。

JavaScriptにおけるハマりポイント

非同期通信(Promiseについて)

PHPなどスクリプト言語をやられている方が
JavaScriptを始めた場合最初にあたる壁かと思います。

例えば下記のような処理

 1: function getLoginUser() {
 2:   return new Promise(function(resolve, reject){
 3:      // ここでDBアクセスなどでデータを取得したとるる
 4:      return resolve({loginCount:100});
 5:   });
 6: }
 7: 
 8: var staff = {};
 9: console.log('A');
10: getLoginUser().then(function(res){
11:   console.log('C');
12:   staff = res;
13: });
14: console.log('B');
15: console.log(staff.loginCount);

上記プログラムを実行した場合、PHP的な感じで行けば15行目のconsole.logでは、
「A -> C -> B -> loginCount:100」と表示されることを期待してしまいます。

非同期処理として処理がいつどのタイミングで実行されるのか、
Promiseの扱い方を理解するまで少し時間がかかるように感じました。

今回の例の場合だと「A -> B -> undefined -> C」と表示されます。

JavaScriptは上から順に処理を実行していくので、
9行目のconsole.logでAを表示した後に、
10行目のgetLoginUser()で処理のみ呼び出しを実施し、
14~15行目の処理が実行されます。
11~12行目は、getLoginUserの非同期処理が実施完了後、callbackで呼ばれるため、
14~15行目よりも後から実行されるという認識になります。

このあたりの非同期処理の基礎が身に付いてこれば、第一段階突破といった感じでしょうか。

JSのシングルトンの扱い

JavaScriptには、クラスという概念が基本的には存在しないので、
新しくオブジェクトを作ればそれがシングルトンになります。

// アイテムのマスター情報と仮定
var Item = {
    name: 'アイテムA',
    point: 200,
  };

特に意識せずにオブジェクトを作成し、変数に入れて使い回しをしたときなどに
このあたりの仕組みを理解せずに利用しているとひどい目に合う場合があります。

上記例の場合で例えば下記のような販売する際には、アイテムの価格を100円にする
などの処理を入れた場合

// buyItemは販売用のアイテムとする
var buyItem = Item;
console.log(Item);
console.log(buyItem);
// 販売するアイテムは100円で割引した価格とする場合
buyItem.point = 100;
console.log(Item);
console.log(buyItem);

上記結果としては、

Object {name: "アイテムA", point: 200}
Object {name: "アイテムA", point: 200}
Object {name: "アイテムA", point: 100}
Object {name: "アイテムA", point: 100}

となり、buyItemのpointの値を変化しただけなのに、Itemのオブジェクトの中身も書き換えられてしまいます。

これは、同一メモリ領域に保存されているデータを参照しているため書き換え処理が発生しております。
そのため、データの書き換えなどを行う際には、
シングルトンの構造把握及びディープコピーの実施などを実施し、
マスターデータとなる実データを扱う場合には要注意となります。

JavaScriptはシングルスレッド

非同期通信を走らせたとしても基本的にはJavaScriptはシングルスレッドで実行しています。
そのためUIの描画やDOM操作、アニメーションなどJSの処理に時間がかかる処理と
ロジックとして処理をゴリゴリ書く処理を並行して実行することが出来ず、
パフォーマンス面で影響が出る可能性があります。

最近では、ServiceWorkerを利用することでメインスレッドとは別で処理を実行できるようになるので
マルチスレッドっぽく並列で処理の高速化を目指した開発するにはServiceWorkerの利用がおすすめです。

最後に

まだまだプロトタイプチェーンやビルド周りの整備、ES2016やTypeScriptなど出せばキリがない部分ですが、
実践的に最初のステップをこえるためには上記知識は必要なのではないかと感じています。

自分たちの技術を高めていくことは、お客様や利用してくれる皆様に
より良いサービスを提供していけることにつながるため、
引き続き日々勉強を心がけて頑張っていけたらなと思います。

brightvie
「あなたの“困った・できたらいいな“をカタチに」 ブライト・ヴィーは手作りのICTシステムをお届けするエンジニアチームです。
https://brightvie.me/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away