Title: Three.jsの前提条件 Description: このサイトを使用するために必要なスキル TOC: 前提条件 これらの記事は、three.jsの使用方法を学習するためものです。 JavaScriptのプログラミング方法を把握してる事を前提とします。 DOMとは何か、HTMLの記述方法、JavaScriptでDOMの作成方法を把握してる事を前提とします。 [es6 modules](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import) のimportや ` ``` パスは絶対パス、または相対パスでなければなりません。相対パスは常に `./` または `../` で始まり `` や `` などの他のタグやcss参照とは異なります。 詳細は[この記事](threejs-fundamentals.html)の最後に記載しています。 ## `document.querySelector` と `document.querySelectorAll` `document.querySelector` を使用し、CSSセレクターに一致する最初の要素を選択できます。 `document.querySelectorAll` は、CSSセレクターに一致するすべての要素を返します。 ## `onbody` は必要ありません 20年前の古いWebページでは、以下のようなHTMLが多く使われてました。 このスタイルは非推奨です。スクリプトをページの下部に配置します。 ```html ... ... ``` または、[deferプロパティを使用します](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script)。 ## クロージャーの仕組みを知る ```js function a(v) { const foo = v; return function() { return foo; }; } const f = a(123); const g = a(456); console.log(f()); // prints 123 console.log(g()); // prints 456 ``` 上記のコードでは、新しい関数が作成される度に関数 `a` を呼び出します。 その関数は変数 `foo` を *閉じ込めます* 。 ここに[詳細な情報](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Closures) があります。 ## `this` がどのように機能するか知る `this` は魔法ではありません。 引数が関数に渡されるのと同じように、関数に自動的に渡される実質的な変数です。 簡単に説明すると、次のような関数を直接呼び出す場合です。 somefunction(a, b, c); `this` は `null`(strictモードまたはモジュールの場合)になりますが、ドット演算子を使用して関数を呼び出す場合と同様です。 someobject.somefunction(a, b, c); `this` は `someobject` がセットされます。 この部分はみなさんが混乱するコールバックです。 const callback = someobject.somefunction; loader.load(callback); これは経験の浅い人が期待するように動作しません。 なぜなら `loader.load` がコールバックを呼び出す時、`.` 演算子で `this` を呼び出していないため、デフォルトではnullになります(ローダーが明示的に何かを設定しない限り) コールバックが発生した時に `this` を `someobject` したい場合は、関数をバインドする必要があります。 const callback = someobject.somefunction.bind(someobject); loader.load(callback); [この記事は `this` を理解するのに役立つかもしれません](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/this). ## ES5/ES6/ES7 stuff ### `var` は非推奨です。 `const` か `let` を使って下さい `var` は使用する理由がありません。varを使用するのは悪い習慣と見なされます。ほとんどの場合、変数の値を変えない場合は `const` を使用します。 値が変更される場合は `let` を使用します。これにより大量のバグを回避できます。 ### `for of` を使用し `for in` は使用しない `for of` は新しい書き方で、 `for in` は古い書き方です。 `for in` で解決できない問題を `for of` が解決しています。 解決した一例として、オブジェクトのすべてのkey/valueのペアを反復処理ができます。 ```js for (const [key, value] of Object.entries(someObject)) { console.log(key, value); } ``` ### `forEach` 、`map` 、 `filter` は役に立ちます 配列の関数である [`forEach`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach) や [`map`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map) 、 [`filter`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter) はモダンなJavaScriptで広く使われています。 ### 分割代入を使う `const dims = {width: 300, height: 150}` のObjectがあるとします。 古いコードの場合 const width = dims.width; const height = dims.height; 新しいコードの場合 const {width, height} = dims; ### オブジェクト宣言のショートカットを使う 古いコードの場合 ```js const width = 300; const height = 150; const obj = { width: width, height: height, area: function() { return this.width * this.height }, }; ``` 新しいコードの場合 ```js const width = 300; const height = 150; const obj = { width, height, area() { return this.width * this.height; }, }; ``` ### スプレット演算子 `...` を使う スプレット演算子にはたくさんの使い方があります。例えば ```js function log(className, ...args) { const elem = document.createElement('div'); elem.className = className; elem.textContent = [...args].join(' '); document.body.appendChild(elem); } ``` もう1つの例 ```js const position = [1, 2, 3]; somemesh.position.set(...position); ``` ### `class` を使う ES5より以前のオブジェクトのようなクラス構文は、ほとんどのプログラマーにはなじみがありませんでした。 ES5以降では、C ++やC#、Javaのスタイルに近い[`class` キーワードを使用](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes) できるようになりました。 ### gettersとsettersを理解する [Getters](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/get) と [setters](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/set) は ほとんどのモダンなプログラミン言語でよく使われます。 ES5のクラス構文により、ES5以前よりもはるかに簡単に使えます。 ### 必要に応じてアロー関数を使います アロー関数はcallbackとPromiseで特に役立ちます。 ```js loader.load((texture) => { // use texture }); ``` アロー関数は `this` をバインドします。 ```js const foo = (args) => {/* code */}; ``` ショートカットで書くなら ```js const foo = (function(args) {/* code */}).bind(this)); ``` ### Promiseはasync/awaitと同様です Promisesは非同期な処理を助ます。Async/awaitはpromiseを助けます。 ここで扱うには大きな話題になるため、[promiseのドキュメントを読んで下さい](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Using_promises)。 また、[async/awaitもドキュメントを読んで下さい](https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Asynchronous/Async_await)。 ### テンプレートリテラルを使用する テンプレートリテラルは、引用符("", '')の代わりにバックティック文字(` `)を使います。 const foo = `this is a template literal`; テンプレートリテラルには基本的に2つの機能があります。1つは複数行にかけます。 ```js const foo = `this is a template literal`; const bar = "this\nis\na\ntemplate\nliteral"; ``` 上記の `foo` と `bar` は同様の意味になります. もう1つは、文字モードの中に `${javascript-expression}` のようにJavaScriptのスニペッドを挿入できます。 これはテンプレートの一部です。例えば ```js const r = 192; const g = 255; const b = 64; const rgbCSSColor = `rgb(${r},${g},${b})`; ``` または ```js const color = [192, 255, 64]; const rgbCSSColor = `rgb(${color.join(',')})`; ``` または ```js const aWidth = 10; const bWidth = 20; someElement.style.width = `${aWidth + bWidth}px`; ``` # JavaScriptのコーディング規則を学びましょう 自由にコードフォーマットする事ができますが、少なくとも1つの規則に注意する必要があります。 JavaScriptの変数名や関数名、メソッド名はすべてローワーキャメルケースです。 コンストラクターやクラスの名前はアッパーキャメルケースです。 このルールに従うなら、他のほとんどのJavaScriptコードと一致します。 多くの [リンター]](https://eslint.org) やコード内の明らかなエラーをチェックするプログラムは、間違ったケースを使用するとエラーを指摘します。 上記の規則に従うことで、エラーが間違っている事がわかるからです。 ```js const v = new vector(); // clearly an error if all classes start with a capital letter const v = Vector(); // clearly an error if all functions start with a lowercase latter. ``` # Visual Studio Codeの使用を検討する もちろんあなたが望むエディタが良いですが、もし望むエディタがなければ [Visual Studio Code](https://code.visualstudio.com/) を使う事を検討してみて下さい。 インストールし [eslintをセットアップ](https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint) します。 セットアップには数分かかる場合がありますが、バグを見つけるのに非常に役に立ちます。 いくつかの例 [`no-undef` ルール](https://eslint.org/docs/rules/no-undef) を有効にすると、VSCodeのEsLintで多くの未定義の変数について警告します。
上記は `doTheThing` のスペルを `doThing` と間違えている事がわかります。 `doThing` の下に赤い波線があり、その上をホバリングすると定義されていない事がわかります。 1つのエラーが回避されました。 `THREE` を使用して警告が表示された場合、eslintに `THREE` が存在する事を伝えるため、JavaScriptファイルの先頭に `/* global THREE */` を追加します。
上記では、eslintは `アッパーキャメルケース` がコンストラクターであるというルールを知っているため、 `new` を使用する必要があります。 他のエラーをキャッチして避けます。これは[`new-cap` ルール](https://eslint.org/docs/rules/new-cap) です。 [数百のEslintルールをオン・オフにカスタム](https://eslint.org/docs/rules/) できます。 上記の例では `var` でなく `const` と `let` を使用するルールを適用しました。 コードでは `var` を使用しましたが、`let` または `const` を使用する必要があると警告されました。
ここでは `let` を使用しましたが、値を変更しない事がわかったため、 `const` を使用することが提案されました。
もちろん、 `var` を使い続けたい場合は、そのルールをオフにすることができます。 上記で記述したように `var` よりも `const` と `let` を使用することを好みます。 それらはうまく機能し、バグを防ぎます。 ルールをオーバーライドする必要がある場合、1行のコードまたはコードセクションに[無効にするコメントを追加できます](https://eslint.org/docs/user-guide/configuring#disabling-rules-with-inline-comments)。 # レガシーブラウザをサポートする必要がある場合は、トランスパイラーを使用して下さい ほとんどのモダンなブラウザは自動更新されるため、これらすべての機能を使用すると便利です。生産性を高め、バグを回避できます。 あなたのプロジェクトで古いブラウザをサポートする必要があれば、[ES5/ES6/ES7コードをES5のJavascriptにトランスパイラーするツール](https://babeljs.io) を使用して下さい。